设置属性时实体框架延迟加载

时间:2015-09-16 18:10:18

标签: c# asp.net entity-framework webforms entity-framework-6

我有一个使用Entity Framework查询数据库的方法,并返回EF对象(ApplicationUser)。如果我有一个ApplicationUser的构造函数试图使用此方法来填充其属性,那么该对象的复杂属性是否会在设置时触发数据库的调用?在原始对象中它们是代理,因此会延迟加载,但只是将这些属性设置为同一对象的新实例的属性调用数据库?

这是一个简单的例子:

public class ApplicationUser
{
    public ApplicationUser(int userId)
    {
        ApplicationUser user = ApplicationUser.Select(userId);
        this.FirstName = user.FirstName //this is fine
        this.ApplicationRole = user.ApplicationRole //This is a complex object. Is it still going to be lazily loaded and called only if this.ApplicationRole is referenced?
    }

    public static ApplicationUser Select(int userId)
    {
        //this uses EF to return an Application User object
    }
}

1 个答案:

答案 0 :(得分:2)

将在此行中调用数据库:

$( ".list-group-item[data-text='Banana'] .badge" ).text(); //50

然后,您的对象将被提取,不再延迟加载。

要确保这种情况发生,您必须进行一些配置:

  1. 必须启用延迟加载和代理创建:

    this.ApplicationRole = user.ApplicationRole;
    
  2. 导航属性必须声明为public Context() : base("YourConnectionString") { Configuration.LazyLoadingEnabled = true; Configuration.ProxyCreationEnabled = true; }

    virutal
  3. 行动中的示例

    假设你有这些课程

    public class ApplicationUser
    {
        //...
        public virtual ApplicationRole ApplicationRole { get; set; }
        //...
    }
    

    第一击:

    public class ApplicationUser
    {
        public int ApplicationUserId { get; set; }
        public string FirstName { get; set; }
        public virtual ApplicationRole ApplicationRole { get; set; }
    
        public static Context db { get; set; }
    
        public ApplicationUser()
        {
    
        }
    
        public ApplicationUser(int userId)
        {
            ApplicationUser user = ApplicationUser.Select(userId);
            this.FirstName = user.FirstName; 
            this.ApplicationRole = user.ApplicationRole; //database will be hit here
        }
    
        public static ApplicationUser Select(int userId)
        {
            //this uses EF to return an Application User object
            return db.Users.Find(userId);
        }
    }
    
    public class ApplicationRole
    {
        public int ApplicationRoleId { get; set;}
        public string Name { get; set; }
    }
    

    生成的SQL:

    return db.Users.Find(userId);
    

    Second Hit

    SELECT
        [Limit1].[ApplicationUserId] AS [ApplicationUserId],
        [Limit1].[FirstName] AS [FirstName],
        [Limit1].[ApplicationRole_ApplicationRoleId] AS [ApplicationRole_Application
    RoleId]
        FROM ( SELECT TOP (2)
            [Extent1].[ApplicationUserId] AS [ApplicationUserId],
            [Extent1].[FirstName] AS [FirstName],
            [Extent1].[ApplicationRole_ApplicationRoleId] AS [ApplicationRole_Applic
    ationRoleId]
            FROM [dbo].[ApplicationUsers] AS [Extent1]
            WHERE [Extent1].[ApplicationUserId] = @p0
        )  AS [Limit1]
    
    -- p0: '1' (Type = Int32)
    

    生成SQL

    this.ApplicationRole = user.ApplicationRole
    

    如果SELECT [Extent2].[ApplicationRoleId] AS [ApplicationRoleId], [Extent2].[Name] AS [Name] FROM [dbo].[ApplicationUsers] AS [Extent1] INNER JOIN [dbo].[ApplicationRoles] AS [Extent2] ON [Extent1].[ApplicationRo le_ApplicationRoleId] = [Extent2].[ApplicationRoleId] WHERE ([Extent1].[ApplicationRole_ApplicationRoleId] IS NOT NULL) AND ([Exte nt1].[ApplicationUserId] = @EntityKeyValue1) -- EntityKeyValue1: '1' (Type = Int32, IsNullable = false) 对象具有其他导航属性,它们仍然会延迟加载,没有问题。

    这里有一个可能有用的提示。要查看EF何时访问数据库,请创建一个控制台应用程序,添加解决方案的引用,然后使用ApplicationRole。要查看有关日志记录的更多信息,请查看此链接https://msdn.microsoft.com/en-us/data/dn469464.aspx