Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When does an Entity Framework linq query return dynamic proxy types and when does it not?

I want to return a single item from my context as follows

using (var context = new MyContext())
{
    var person = context.People.OrderByDescending(x => x.LastUpdatedDate).FirstOrDefault();
}

My context looks like:

public DbSet<Person> People { get; set; }

Why is it that the type of my person variable above is not Person but the dynamic proxy type such as System.Data.Entity.DynamicProxies .Person_5E43C6C196972BF0754973E48C9C941092D86818CD94005E9A759B70BF6E48E6?

If I use Find, then I do get the type as Person. I want to return the top 1 record as ordered by the last update date and OrderByDescending / FirstOrDefault seemed like the most logical approach.

I realise I could turn off dynamic proxy generation but I don't think this is necessary.

Suppose my question is which linq methods cause the object to be returned as the type you might expect and which return the dynamic proxy type?

like image 741
obaylis Avatar asked Sep 22 '15 15:09

obaylis


1 Answers

As I see in Entity Framework source code, it is not related to any linq method. When creating the result, it checks if the ProxyCreationEnabled is true, then it checks that if a proxy can be created for type, then creates a proxy for it. And here is the rule for checking if can proxy type:

private static bool CanProxyType(EntityType ospaceEntityType)
{
    TypeAttributes access = ospaceEntityType.ClrType.Attributes & TypeAttributes.VisibilityMask;

    ConstructorInfo ctor = ospaceEntityType.ClrType.GetConstructor(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.CreateInstance, null, Type.EmptyTypes, null);
    bool accessableCtor = ctor != null && (((ctor.Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Public) ||
                                            ((ctor.Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Family) ||
                                            ((ctor.Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.FamORAssem));

    return (!(ospaceEntityType.Abstract ||
                ospaceEntityType.ClrType.IsSealed ||
                typeof(IEntityWithRelationships).IsAssignableFrom(ospaceEntityType.ClrType) ||
                !accessableCtor) &&
                access == TypeAttributes.Public);
}

Also from this msdn link: Note that the EF will not create proxies for types where there is nothing for the proxy to do. This means that you can also avoid proxies by having types that are sealed and/or have no virtual properties.

like image 117
Reza Aghaei Avatar answered Oct 05 '22 19:10

Reza Aghaei