Apply Include and ThenInclude based on Lambda Expressions Dictionary




I have a few Entity Framework 7 (Core) entities:



```
public class Person {
   public virtual Address Address { get; set; }
   public virtual ICollection<Hobby> Hobbies { get; set; }
}

public class Address {
   public String Street { get; set; }
   public virtual Country Country { get; set; }
}

```

And I have a string array as follows:



```
String[] entities = new String[] { "Hobbies", "Address.Country" }

```

Given this string array I got:



```
context.Persons
  .Include(x => x.Hobbies)
  .Include(x => x.Address).ThenInclude(x => x.Country);

```

In EF6 I could do something like:



```
context.Persons.Include(entities[0]).Include(entities[1]);

```

But in EF7 Include does not allow strings. I created the dictionary:



```
private readonly Dictionary<String, LambdaExpression> _properties = new Dictionary<String, LambdaExpression>();

```

Which would have something like:



```
x => x.Hobbies is for "Hobbies"
x => x.Address.Country is for "Address.Country"     

```

And I have the extension:



```
public static IQueryable<T> Include<T>(this IQueryable<T> source, Dictionary<String, LambdaExpression> properties) {
}

```

Where I need to given the Dictionary apply the following:


1. For "x => x.Hobbies" just do: 



```
 source.Include(x => x.Hobbies);

```
2. If the expression is something like "x => x.Address.Country" add: 



```
 source.Include(x => x.Address).ThenInclude(x => x.Country);

```


Can this be done?
Not sure about `ThenInclude()` and EF 7, but you can do something like this in your repositories (tested with EF 6):



```
public MyEntity GetMyEntity_EagerlyLoad(DbContext context, int id, params Expression<Func<MyEntity, object>>[] propertiesToLoad)
{
    var q = context.MyEntities.Where(m => m.ID == id);

    foreach (var prop in propertiesToLoad)
        q = q.Include(prop);

    return q.SingleOrDefault();
}

```

You can then call it like this:



```
repo.GetMyEntity_EagerlyLoad(context, id, m => m.Property1, m => m.Property2, m => m.Property1.NestedProperty)

```

  



**EDIT**: There is also the alternative way to do eager loading with EF using projection. You could do a generic repository method like this:



```
public MyEntity GetMyEntity_EagerlyLoad<T>(DbContext context, int id, Expression<Func<MyEntity, T>> loadingProjection, Func<T, MyEntity> resultProjection)
{
    var q = context.MyEntities.Where(m => m.ID == id);

    return q.Select(loadingProjection).AsEnumerable().Select(resultProjection).SingleOrDefault();
}

```

And then call it with the properties you want loaded and the entity you want the method to return:



```
repo.GetMyEntity_EagerlyLoad(context, id, m => new { myEntity = m, m.Property1, m.Property2, m.Property1.NestedProperty }, m => m.myEntity)

```
Using [reflection](/questions/tagged/reflection "show questions tagged 'reflection'") and [expression-trees](/questions/tagged/expression-trees "show questions tagged 'expression-trees'") you can provide the parameters and then call `OrderBy` function, Instead of returning `Expression<Func<Task, T>>` and then calling `OrderBy`.


Note that `OrderBy` is an extension method and has implemented in both `System.Linq.Enumarable` and `System.Linq.Queryable` classes. The first one is for [linq-to-objects](/questions/tagged/linq-to-objects "show questions tagged 'linq-to-objects'") and the latter is for [linq-to-entities](/questions/tagged/linq-to-entities "show questions tagged 'linq-to-entities'"). [entity-framework](/questions/tagged/entity-framework "show questions tagged 'entity-framework'") needs the expression tree of the query in order to translate it to SQL commands. So we use the `Queryable` implementation.


It can be done by an extension method(explanations added as comments):



```
public static IOrderedQueryable<TSource> OrderBy<TSource>(
       this IQueryable<TSource> query, string propertyName)
{
    var entityType = typeof(TSource);

    //Create x=>x.PropName
    var propertyInfo = entityType.GetProperty(propertyName);
    ParameterExpression arg = Expression.Parameter(entityType, "x");
    MemberExpression property = Expression.Property(arg, propertyName);
    var selector = Expression.Lambda(property, new ParameterExpression[] { arg });

    //Get System.Linq.Queryable.OrderBy() method.
    var enumarableType = typeof(System.Linq.Queryable);
    var method = enumarableType.GetMethods()
         .Where(m => m.Name == "OrderBy" && m.IsGenericMethodDefinition)
         .Where(m =>
         {
            var parameters = m.GetParameters().ToList();
            //Put more restriction here to ensure selecting the right overload                
            return parameters.Count == 2;//overload that has 2 parameters
         }).Single();
    //The linq's OrderBy<TSource, TKey> has two generic types, which provided here
    MethodInfo genericMethod = method
         .MakeGenericMethod(entityType, propertyInfo.PropertyType);

    /*Call query.OrderBy(selector), with query and selector: x=> x.PropName
      Note that we pass the selector as Expression to the method and we don't compile it.
      By doing so EF can extract "order by" columns and generate SQL for it.*/
    var newQuery = (IOrderedQueryable<TSource>)genericMethod
         .Invoke(genericMethod, new object[] { query, selector });
    return newQuery;
}

```

Now you can call this overload of `OrderBy` like any other overload of it.  

For example:



```
var cheapestItems = _context.Items.OrderBy("Money").Take(10).ToList();

```

Which translates to:



```
SELECT TOP (10)  {coulmn names} FROM  [dbo].[Items] AS [Extent1] 
       ORDER BY [Extent1].[Money] ASC

```

This approach can be used to define all overloads of `OrderBy` and `OrderByDescending` methods to have `string` property selector. In your example, the category data is stored in an attribute, rather than within the node itself.


You therefore need to use the XPath: `/product[1]/categories/category/@path` where the @ shows you want to target an attribute. Let's say in your `settings.py` file you have:



```
SITE_URL='www.mydomain.tld/somewhere/'
SITE_NAME='My site'

```

**If you need that in just one or two views:**



```
from django.shortcuts import render_to_response
from django.conf import settings

def my_view(request, ...):
    response_dict = {
        'site_name': settings.SITE_NAME,
        'site_url': settings.SITE_URL,
    }
    ...
    return render_to_response('my_template_dir/my_template.html', response_dict)

```

**If you need to access these across a lot of apps and/or views, you can write a context processor to save code:**


James has a tutorial on this 
[online](http://www.b-list.org/weblog/2006/jun/14/django-tips-template-context-processors/).


Some useful information on the when and if of context processors is available on this very site 
[here](https://stackoverflow.com/questions/831301/when-is-it-appropriate-to-use-django-context-processors).


Inside your `my_context_processors.py` file you would:



```
from django.conf import settings

def some_context_processor(request):
    my_dict = {
        'site_url': settings.SITE_URL,
        'site_name': settings.SITE_NAME,
    }

    return my_dict

```

Back in your `settings.py`, activate it by doing:



```
TEMPLATE_CONTEXT_PROCESSORS = (
    ...

    # yours
    'my_context_processors.some_context_processor',
)

```

In your `views.py`, make a view use it like so:



```
from django.shortcuts import render_to_response
from django.template import RequestContext

def my_view(request, ...):  
    response_dict = RequestContext(request)
    ...
    # you can still still add variables that specific only to this view
    response_dict['some_var_only_in_this_view'] = 42
    ...
    return render_to_response('my_template_dir/my_template.html', response_dict)

``` A few things to try.


1. Use [Variable Tables](http://odetocode.com/Articles/365.aspx) instead -> maybe the import wizard prefers that?
2. Name your return fields.


Try using the following stored proc (untested .. just thinking out loud...)



```
CREATE PROCEDURE dbo.Foo
AS

    SET NOCOUNT ON

    DECLARE @ResultTable TABLE (SomeId INTEGER)

    INSERT INTO @ResultTable
    SELECT DISTINCT Id AS Identity -- Or u can rename this field to anything...
    FROM SomeExistingTableWhichHasAnIdentityField

GO

```

Try that and see if the wizard refreshes, now.


-- 


 Attempt #2 :)


Ok .. when the EF designer/wizard/whatever fails to figure out EXACTLY what my stored proc is suppose to be returning, I usually do the following :-


1. Make sure the stored procedure doesn't exist at all in the EF designer/context, etc. (You have a clean starting point)
2. Open up your stored procedure and `/* /*` comment out *EVERYTHING* after the procedure definition.


eg..



```
ALTER PROCEDURE dbo.Foo
(
    Bar1 INT,
    Bar2 TINYINT,
    ... // whatever u have as your optional input arguments //
)
AS
    SET NOCOUNT ON

    /* 
    .... every thing in here is commented out 
    */
GO

```

Now ...
 3. Add a forced fake return in the stored proc, which (more or less) just *defines* the output structure/fields.


eg..



```
ALTER PROCEDURE dbo.Foo
(
    Bar1 INT,
    Bar2 TINYINT,
    ... // whatever u have as your optional input arguments //
)
AS
    SET NOCOUNT ON

    SELECT 1 AS Id, 1 AS UserId, 1 AS SomeOtherId, 
        CAST('AAA' AS NVARCHAR(350)) AS Name,
        -- etc etc etc..
    /* 
    .... every thing in here is commented out 
    */
GO

```

[and then](http://www.youtube.com/watch?v=K7luMp6lb9M) ...


4. Add this stored proc to your EF designer/wizard/etc... Now the correct fields should be 'determined' by the designer. AWESOME. Yes .. the values are all hardcoded .. but that's ok (so far).
5. Once your happy that EF is now updated right, go back to your stored proc, and remove all hardcoded SELECT (which we did in the above step). Now we remove the comments which we commented out the entire real code. So you should have your original stored proc, back.


... and now EF is updated and doesn't know we've changed the plumbing of your stored proc.


win :)


does this work for ya? Your test is redundant, since you are already querying only for matching records. In this case, you will get no rows if there is no match, therefore you will never hit the else clause in the loop.  

  

Instead, it is enough to check if there are any matching records at all. The example below shows how (note that you can put a condition straight into Any() instead of specifying Where()).  

  

C#Copy Code

```
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
 
namespace CustomerMaster
{
    public partial class CustomerMaster : System.Web.UI.Page
    {
 
        private void AddData()
        {
            
            OperationsDataContext AddDb = new OperationsDataContext();
            CustomerMast cm = new CustomerMast();
            
                        
            cm.CustomerCode = txtCustCde.Text;
            cm.CustomerName = txtCustName.Text;
            cm.CustomerAddress = txtCustAdd.Text;
            cm.BrkrCode = txtBrkCode.Text;
            cm.BrokerName = txtBrkName.Text.
            cm.CrrCode = txtCrrCode.CarrierCode;
            cm.CarrierName =  txtCrrName.Text;
            cm.StnCode=sm.StationCode;
            cm.StationName = txtStnName.Text;
            cm.VatNo=txtVatNo.Text;
            cm.TinNo=txtTinNo.Text;
            cm.TMCO=txtTMCONo.Text;
            cm.PanNo = txtPAN.Text;
			
	    if(AddDb.CustomerMasts.Any(c=>c.CustomerCode == txtCustCde.Text))
            {
	        Response.Write("Error! CustomerCode Exits");
	    }
	    else
	    {
                AddDb.BrokerMasts.InsertOnSubmit(bm);
                AddDb.CarrierMasts.InsertOnSubmit(crm);
                AddDb.StationMasts.InsertOnSubmit(sm);
                AddDb.CustomerMasts.InsertOnSubmit(cm);

	        AddDb.SubmitChanges();
            }         
        }
 
        protected void btnAdd\_Click(object sender, EventArgs e)
        {
            AddData();
        }
    }
}
``` I don't know if this actually solves your issue, but I had the same problem and tried pretty much every solution out there.


Eventually, after installing the correct packages to support VS2012, I also installed [Entity Framework 6 Tools for Visual Studio 2012 & 2013](http://www.microsoft.com/en-us/download/details.aspx?id=40762)


After doing so (and a restart of VS) the connection showed up in the Entity Data Model Wizard.


Hope it solves your issue as well. The object you are linking with was built with the option to use the static run-time libraries, whereas your DLL was (properly) built to use the DLL libraries. When you mix these you'll get complaints such as this.


Since Fortran objects don't care which library set is used (this is not true of C/C++), one option could be to set the Linker>Input property "Ignore all default libraries" (/NODEFAULTLIB) in your DLL project. You will then need to name the required libraries under Additional Dependencies. (You can use the dumpbin command on your DLL's object to see a list.)


If you can rebuild the external object, do so with the Fortran > Libraries > Disable default library search rules property set to Yes. Then you should be able to link it in without further issue.




[View solution in original post](/t5/Intel-Fortran-Compiler/Error-linking-to-external-obj-file/m-p/1144075#M138021) unfortunately that's not how it works. it's db mapping, and we're talking about joined-tables hierarchy. so the "other side" of the association must be in the referenced table (the detail one, not custom detail). sorry i took so long to respond on this post. i’ve had a busy week! so i found the issue. in my template for endpoints i realized i accidentally set them to provision using the external ip address of my pbx. changed it to internal and this fixed my issues :stuck\_out\_tongue: In order to correctly map you need to use the multi-map functionality.



```
 var points = this._db.Query<Point, Address, Point>("select p.Id, 'x' [Id], p.Address_City [City], p.Address_State [State] from Points p", (p, a) =>
            {
                p.Address = a;
                return p;
            }).ToList();

```