查询EDMX中的多对多连接表

时间:2015-07-08 10:38:06

标签: c# sql-server linq entity-framework linq-to-entities

每当我访问实体的导航属性时,我目前都面临性能问题。

我有三个表:UserCategoryUserUserCategoryUserUserUserCategory表之间存在多对多关系。 UserCategoryUser表是joiner表,它有两列 UserId UserCategoryId ,即UserUserCategory表的主键。加入者表UserCategoryUser用于维护UserUserCategory表之间的多对多关系。

我使用数据库优先方法。因此,在我的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或存储过程进行此检查,但我想远离这种情况。

1 个答案:

答案 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