0

Here's my LINQ query:

    var settingViewModels = from l in settingsByEnvironment["Localhost"]
                                join d in settingsByEnvironment["Dev"] on l.Key equals d.Key
                                join p in settingsByEnvironment["Prod"] on d.Key equals p.Key
                                select new MyKeyValue
                                {
                                    Key = p.Key,
                                    LocalhostValue = l.Value,
                                    DevValue = d.Value,
                                    ProdValue = p.Value
                                };

As you see, I've hard coded the three environment Localhost, Dev, and Prod in two parts of my code.

What if tomorrow, I have a new environment? My code is not dynamic.

I tried to use ExpandoObject, but still I cannot have a full dynamic query. Here's the equivalent of my previous LINQ code using ExpandoObject;

// listSettingsEnvLocalhost is of type Tuple<string (environmentName), List<SettingViewModels>>


    public void GetSettingsValueForEachEnvironment()
    {

       var foo = from p in listSettingsEnvLocalhost.Item2
           join a in listSettingsEnvDev.Item2 on p.Key equals a.Key
           let environmentLocalhost = listSettingsEnvLocalhost.Item1
           let environmentDev = listSettingsEnvDev.Item1
           select ToExpando(p, a, environmentLocalhost, environmentDev);
    }

    private dynamic ToExpando(SettingViewModel first, SettingViewModel second, string environmentLocalhost, string environmentDev)
    {
        dynamic o = new ExpandoObject();
        ((IDictionary<string, object>)o).Add("Key", first.Key);
        ((IDictionary<string, object>)o).Add(environmentLocalhost, first.Value);
        ((IDictionary<string, object>)o).Add(environmentDev, second.Value);
        return o;
    }

Is an expression tree a solution?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
John
  • 4,351
  • 9
  • 41
  • 57
  • using from without join causes to Cartesian product and I think it's not useful in your case, so use join, also too many joins (i.e more than three) can cause to bad performance, I think if is possible, review your design and do it in another way. – Saeed Amiri Sep 26 '11 at 09:55
  • Thanks for your comment, I'm gonna edit my post to use a join – John Sep 26 '11 at 11:38

2 Answers2

2

If you want create a dynamic query, you can use dynamic LINQ operators that are available at this link: http://msdn.microsoft.com/en-us/bb330936.aspx (download the C# example and get the code in the \LinqSamples\DynamicQuery directory)

There is also a dynamic Join operator defined by Royd Brayshay. See Stack Overflow question How to create a dynamic LINQ join extension method.

Community
  • 1
  • 1
Massimo Zerbini
  • 3,125
  • 22
  • 22
  • The sample DynamicQuery seems to fit my needs, do you have a example about how to translate my multiple from using dynamic query ? The example given use lambda expression with hard coded collection: var query = db.Customers.Where("City == @0 and Orders.Count >= @1", "London", 10). OrderBy("CompanyName"). Select("New(CompanyName as Name, Phone)"); – John Sep 26 '11 at 09:11
  • @John some examples are on the web, this article for dynamic Where conditions http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx and see Royd Brayshay example for Join example or multiple from – Massimo Zerbini Sep 26 '11 at 09:23
  • I analyse the sample given by Royd Brayshay, I understand the Join(...) part as it's a string in param I can dynamically generate it, but I dont manage to understand how he is able to dynamically query several collections, as to say multiple from. In his code, he specically write: var cat = (db.A as IQueryable) but what's the db.A in my case ? – John Sep 26 '11 at 09:45
  • yes 'db.A' is a list of objects ( list of a type of objects that maps a table on the db ), think that 'db.A' is like your collections – Massimo Zerbini Sep 26 '11 at 10:25
  • ok but how I can loop for each of my listByEnvironment then doing a join? – John Sep 26 '11 at 11:59
  • I'll stay with hard coded linq, perhaps I'll try with Expression trees. :) Thanks by the way, I didn't know Dynamic Linq exits. I took time to have fun with it, but the part where it needs string is a bit depressing (no syntaxtic color, no compilation) even if I'm not sure there could be a better solution. :) – John Sep 26 '11 at 15:24
  • The first link seems to be half-broken now. It redirects to a somewhat generic page. – Peter Mortensen Apr 26 '15 at 11:38
0

I would store your setting variables in a dictionary instead. Then it would be more dynamic. The dictionary should look like Dictionary<string, Dictionary<string, string>.

The first key is environment and the key in the inner dictionary is the settings key. Then you would be all set, and it would be dynamic.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Tomas Jansson
  • 22,767
  • 13
  • 83
  • 137
  • Unfortunately I'll still have three Dictionary functions of the number of environment I have and thats equal to the number of DataStore I have. For exemple, in Dev environment I have a sql server, but in Prod I also have a sql server. So I have to query each environment and I'll get my query with multiple from. – John Sep 26 '11 at 09:19
  • I think you should clarify your question a little bit with what you want to achieve. As it is now it only says, "here is some linq, is this the right way?" Try to forumalte exactly what your problem is and what you are trying to solve, then it will be much easier to help you. – Tomas Jansson Sep 26 '11 at 10:14
  • Tomas, thanks for your comment, you're absolutely right. I'm going to edit my post to make it clearer. – John Sep 26 '11 at 11:25