在 EDMX 中查询多对多连接器 table

Query to many-to-many joiner table in EDMX

我目前在访问实体的导航 属性 时遇到性能问题。

我有三个 table:UserCategoryUserUserCategoryUser。在 UserUserCategory table 之间存在 多对多 关系。 UserCategoryUser table 是连接器 table 它有两列 UserIdUserCategoryId 即主键UserUserCategory table 秒。 joiner table UserCategoryUser 用于维护 UserUserCategory tables.

之间的多对多关系

我正在使用数据库优先方法。因此在我的 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 中执行连接查询,因为加入者 table(UserCategoryUser) 未作为实体添加到 EDMX 中。

如何解决这个问题?我可以使用纯 SQL 或存储过程进行此检查,但我想远离这种情况。

您的问题是,启用延迟加载后,对 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