简体   繁体   English

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

[英]Entity Framework Lazy Loading When Setting Properties

I have a method that queries the database using Entity Framework, and returns the EF object (ApplicationUser). 我有一个使用实体框架查询数据库并返回EF对象(ApplicationUser)的方法。 If I have a constructor for ApplicationUser that tries to use this method to populate its properties, will the complex properties of that object trigger the database to be called when they are set? 如果我有一个ApplicationUser的构造函数,尝试使用此方法填充其属性,那么设置该对象时,该对象的复杂属性会触发数据库被调用吗? In the original object they are proxies, and therefore would be lazy loaded, but will merely setting those properties to properties of a new instance of the same object call the database? 在原始对象中,它们是代理,因此将被延迟加载,但是仅将那些属性设置为同一对象的新实例的属性会调用数据库吗?

Here's a simple example: 这是一个简单的例子:

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

The database will be called in this line: 数据库将在以下行中调用:

this.ApplicationRole = user.ApplicationRole;

Then, your object will be fetched and will not be lazy loaded any more. 然后,将获取您的对象,并且不再延迟加载。

To make sure that this will happen, you have to do some configuring: 为确保发生这种情况,您必须进行一些配置:

  1. lazy loading and proxy creation must be enabled: 必须启用延迟加载和代理创建:

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

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

EXAMPLE IN ACTION 实际例子

Supposed that you have these classes 假设您有这些课程

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

First Hit: 第一击:

return db.Users.Find(userId);

Generated SQL: 生成的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)

Second Hit 第二击

this.ApplicationRole = user.ApplicationRole

Generated SQL 生成的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)

If the ApplicationRole object has other navigation properties, they will still be lazy-loaded, without problems. 如果ApplicationRole对象具有其他导航属性,则它们仍将被延迟加载,而不会出现问题。


Here comes a tip that might be helpful. 这里有一个提示可能会有所帮助。 To see when EF is hitting the database, create a console app, add a reference of your solution, and use the context.Database.Log . 要查看EF何时访问数据库,请创建一个控制台应用程序,添加解决方案的引用,然后使用context.Database.Log To see more about logging, take a look at this link https://msdn.microsoft.com/en-us/data/dn469464.aspx 要查看有关日志记录的更多信息,请查看此链接https://msdn.microsoft.com/zh-cn/data/dn469464.aspx

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

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