简体   繁体   中英

Entity Framework Lazy Loading When Setting Properties

I have a method that queries the database using Entity Framework, and returns the EF object (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? 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 :

     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:

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

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.


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 . To see more about logging, take a look at this link https://msdn.microsoft.com/en-us/data/dn469464.aspx

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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