每当我访问实体的导航属性时,我目前都面临性能问题。
我有三个表:UserCategory
,User
和UserCategoryUser
。 User
和UserCategory
表之间存在多对多关系。 UserCategoryUser
表是joiner表,它有两列 UserId 和 UserCategoryId ,即User
和UserCategory
表的主键。加入者表UserCategoryUser
用于维护User
和UserCategory
表之间的多对多关系。
我使用数据库优先方法。因此,在我的EDMX中,对于User
实体,我有一个导航属性UserCategories
。类似地,对于UserCategory
实体,存在导航属性Users
。
我想将用户添加到用户类别。所以在添加之前,我要检查用户是否已经添加到用户类别中。在我的数据库中,我有 100k 用户记录和一个用户类别。所有用户都与唯一的用户类别相关联。
我正在访问Users
导航属性,如下所示:
var userCategory = Context.UserCategories.FirstOrDefault(uc => uc.UserCategoryId == userCategoryId);
if (userCategory != null)
{
if (userCategory.Users.Any(u => u.Username == username))
{
//Other operations
}
}
此代码之前正在运行,但由于我们拥有大量用户数据,因此它暂停了。
特别是它挂在userCategory.Users.Any(u => u.Username == username))
行。我也试过让用户count
,但它仍然悬挂!
userCategory.Users.Count();
我无法在LINQ to Entity中执行连接查询,因为joiner表(UserCategoryUser
)未作为实体添加到EDMX中。
如何解决这个问题?我可以使用纯SQL或存储过程进行此检查,但我想远离这种情况。
答案 0 :(得分:2)
您的问题是,启用延迟加载后,对userCategory.Users
的调用会将所有用户加载到内存中。我认为,鉴于类别很少,我会反过来这样做。即,获取用户然后检查用户的类别集合是否包含要添加的类别。
但是,如果您有非常多的类别,那么您可以明确过滤该集合。首先关闭集合上的延迟加载(例如,删除virtual
关键字),然后尝试:
Context.Entry(userCategory)
.Collection(uc => uc.Users)
.Query()
.Where(u => u.Username == username)//I'd put an index on username too
.Load();
if(userCategory.Users.Any())
{
//Other operations
}
参考:https://msdn.microsoft.com/en-us/data/jj574232.aspx#explicitFilter