本文介绍了实体框架核心-访问实体上集合的最佳方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个简单的ASP.NET Core 2.0 + Entity Framework Core项目:

I have a simple ASP.NET Core 2.0 + Entity Framework Core project:

我有一个名为ApplicationUser的实体,该实体扩展了Microsoft.AspNet.Identity.IdentityUser,而ApplicationUser有一个名为Books的另一个实体的集合.

I have an entity called ApplicationUser, which extends Microsoft.AspNet.Identity.IdentityUser, and the ApplicationUser has a collection of another entity called Books.

但是,当我尝试从UserManager中检索书集之后,我尝试从ApplicationUser中读取书集:

However, when I try to read the collection of Books from the ApplicationUser after retrieving it from UserManager:

ApplicationUser user = await _userManager.GetUserAsync(User);
return user.Books;

我得到一个空的收藏集.

I get an empty collection.

如果我改为这样做:

ApplicationUser user = await _userManager.GetUserAsync(User);
return _context.Users.Include(d => d.Books).FirstOrDefault(u => u == user);

然后我得到了正确的藏书.

Then I get the correct collection of Books.

我怀疑这是因为我从UserManager检索到的ApplicationUser缺少适当的DbContext. 我的问题是,有更好的方法吗?就像能够以某种方式仅从用户那里获取集合,而不必通过LINQ遍历DbContext一样?会有明显的性能提升吗?

I suspect this is because the ApplicationUser I retrieved from the UserManager lacks the proper DbContext. My question is, is there a better way of doing this? Like somehow being able to just get the collection from the user without having to go through the DbContext with LINQ? Would there be significant performance gain?

最后,对EF Core有什么好的了解,以了解它在幕后的工作原理?

Finally, what would be a good read about EF Core to get an understanding of how it works under the hood?

推荐答案

首先,如果要访问数据库中的数据,则必须使用DBContext.其次,仍然可以从另一个对象访问数据库的唯一方法是,如果对象的类型是IQueryable,而该类型是直接或间接从数据库返回的.

First of, if you want to access data from your database, you must use DBContext. Secondly, the only way you can still access the database from another object is if the object was of type IQueryable that was returned directly or indirectly from the database.

例如,以下内容将返回IQueryable<User>:

For instance, the following would return IQueryable<User>:

var users = _context.Users.Where(u => u == user);

这意味着您可以访问users变量并访问数据库,如下所示:

This means you can access the users variable and access the database something like this:

var books = users.Select(u => u.Books);

请注意,_userManager.GetUserAsync(User)函数不会返回IQueryable.这意味着ApplicationUser user将仅包含要获取的内容(用户对象).简单地使用user.Books并不能帮助它从数据库中获取数据.而且,如果我没有记错的话,GetUserAsync将从当前声明主体而不是数据库中获取其数据.无论哪种方式,当您尝试获取用户时,实体框架都不会自动获取书本.正如Igor所提到的,由于延迟加载. https://docs.microsoft.com/en-us/ef/core/querying/related-data

Notice the _userManager.GetUserAsync(User) function does not return an IQueryable. This means that the ApplicationUser user will only contain what it was meant to fetch (the user object). Simply using user.Books will not help it fetch data from the database. Moreover, if I am not mistaken, GetUserAsync gets its data from the current claims principal, not the database. Either way, when you attempt to fetch the user, entity framework will not automatically fetch Books as well. This is as Igor mentioned due to lazy loading. https://docs.microsoft.com/en-us/ef/core/querying/related-data

关于您的方式有多优化,您可以检查控制台中正在运行的确切SQL查询.由于ef core会将这些行放在一起并确切了解要运行的查询,因此上述方法肯定会运行单个查询.

As for how optimized your ways are, you can check the exact SQL query being run in your console. The above way I have shown will surely run a single query since ef core will put those lines together and understand exactly what query to run. A straightforward way to access the same data would be something like

_context.Books.Where(b => b.User == user)

如果这是您打算使用user的全部功能,则使用_userManager.GetUserId()的性能会更好一些,因为它只会从您的声明中获得一个价值.然后您可以使用:

If this is all you plan to use user for, it would have a little better performance to use _userManager.GetUserId(), since it would only get one value from your claims. Then you can use:

_context.Books.Where(b => b.UserId == userId)

这篇关于实体框架核心-访问实体上集合的最佳方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-03 21:41