繁体   English   中英

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

[英]Entity Framework Lazy Loading When Setting Properties

我有一个使用实体框架查询数据库并返回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
    }
}

数据库将在以下行中调用:

this.ApplicationRole = user.ApplicationRole;

然后,将获取您的对象,并且不再延迟加载。

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

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

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

     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; }
}

第一击:

return db.Users.Find(userId);

生成的SQL:

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)

第二击

this.ApplicationRole = user.ApplicationRole

生成的SQL

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)

如果ApplicationRole对象具有其他导航属性,则它们仍将被延迟加载,而不会出现问题。


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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM