简体   繁体   中英

ASP.NET Core 2 Identity/Entity Framework - How to get the custom properties within the User class?

Currently I do obtain the user with:

ApplicationUser currentUser = await _userManager.GetUserAsync(User);

but I found that in this way it doesn't hold custom properties, for example:

public virtual UserImage UserImage { get; set; }

so every time that I need to get such property I write a method to get from the db with entity-framework, like:

public async Task<UserImage> GetUserImage(string userId) =>
        await _dBcontext.UserImage.SingleOrDefaultAsync(u => u.ApplicationUserId == userId);

I would like to cache within the application(on the server, not cookie) all the user properties by only calling

await _userManager.GetUserAsync(User);
There is such a way?

Have a look at this thread: asp.net forum

Rules for lazy loading:

context.Configuration.ProxyCreationEnabled should be true. context.Configuration.LazyLoadingEnabled should be true. Navigation property should be defined as public , virtual . Context will NOT do lazy loading if the property is not defined as virtual.

I hope this will help ;)

I'm going to assume that you're actually using Entity Framework Core, even though your question is tagged with just entity-framework. The reason is that what you have would just naturally work with Entity Framework, whereas, it will definitely not work at all with Entity Framework Core.

The key difference between the two is that EF Core does not support lazy-loading. With EF virtual navigation properties, a proxy class is dynamically created that derives from your entity class. The navigation properties are then dynamically overridden to add EF's lazy-loading logic to the getters. This causes an access of the property getter to invoke said lazy-loading logic and issue a query to the database to materialize the related entity or entities.

Since EF Core does not support lazy-loading, none of this occurs. As a result, unless you eagerly or explicitly load the relationship, it remains null. However, lazy-loading is a bad idea in the first place. It can lead to huge inefficiencies such as the 1+N query issue, where for example, you iterate over a list and end up issuing a query per item in the list to materialize some relationship on that item. If you have a lot of items, you can end up issuing a ton of queries, particularly if there's other relationships involved further in the tree. Say for example that you have a list of items with a related entity and then that related entity itself has a related entity you need to access. Now, you're issuing even more queries fetch that related entity each time. It can get out of control very quickly.

Long and short, it's far better to eagerly load the relationships you need. That will actually cause JOINs to issued in the initial query to fetch all the relationships at the same time, in just that one query. Short of that, explicit loading is still superior, as at least you are then aware of specific queries you are issuing and can clearly see if things start to get out of hand.

UserManager , however, does not give you any opportunity to do eager loads. As a result, if you use it to get the user, your only option is an explicit load of the related entity. That's not necessarily a bad thing, though, as it's only one additional query.

var currentUser = await _userManager.GetUserAsync(User);
await _dbContext.Entry(currentUser).Reference(u => u.UserImage).LoadAsync();

Now, you can access the related image.

Alternatively, you can query the user from the context, instead, and then eagerly load the image at the same time:

var currentUser = await _dbContext.Users.Include(u => u.UserImage).SingleOrDefault(u => u.Id == User.Identity.GetUserId());

That will issue just one query with a join on the image relationship.

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