如何在EF6.1中过滤掉子集合

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在EF6.1中过滤掉子集合相关的知识,希望对你有一定的参考价值。

我有一个Apps,AppRoles,UserAppRoles和用户。我正在尝试获取所有用户,但只想要AppRd = AppId = 1的AppRoles。如何过滤子集合?

using (var context = new dbContext())
            {
                var rv = context.Users
                       .Include(u => u.AppRoles);                           

            }

我试过这个但抛出异常:Include路径表达式必须引用在类型上定义的导航属性。使用虚线路径作为参考导航属性,使用Select运算符作为集合导航属性

public static async Task<List<User>> GetAllAsync()
        {
            var rv = new List<User>();

            using (var context = new dbContext())
            {
                rv = await (context.Users.AsNoTracking()
                    .Include(a => a.AppRoles.Where(a2 => a2.AppId == 1)).ToListAsync());
            }

           return rv;

        }

我可以弄清楚如何让它工作的唯一方法就是这样,我可能只是在那时使用存储过程:

var rv = new List<User>();

            using (var context = new dbContext())
            {
               rv = context.Users.AsNoTracking()
                    .Include(a => a.AppRoles).ToList();


            }

            foreach (var user in rv)
            {
                if (user.AppRoles.Any())
                {
                    user.AppRoles = user.AppRoles.Where(r2 => r2.AppId == 1).ToList();
                }
            }

我怎么用EF写这个?

SELECT        
Users.UserId, 
Users.UserName
FROM          
Users 

INNER JOIN UserAppRoles ON Users.UserId = UserAppRoles.UserId 
INNER JOIN AppRoles ON UserAppRoles.AppRoleId = AppRoles.AppRoleId
WHERE AppRoles.AppId = 1
答案

试试这个:

context.Entry(user) 
        .Collection(b => b.AppRoles) 
        .Query() 
        .Where(r => r.AppId==1) 
        .Load(); 

其中user是来自上下文的AppUser实体(如您的foreach示例中所示)。

更多信息:

https://msdn.microsoft.com/en-us/library/jj574232(v=vs.113).aspx(“在显式加载相关实体时应用过滤器”部分)

另一答案

您可以查询AppRoles

var arQuery = from ar in context.AppRoles
              where ar.AppId == 1
              select ar;

var query = from u in context.Users
            join uar in context.UserAppRoles on u.UserId equals uar.UserId
            join ar in arQuery on uar.AppRoleId equals ar.AppRoleId
            select u;
另一答案

我有这样的工作,但仍然看起来效率低但是猜测它比往返数据库更好。这不是一个常见的模式吗?我不敢相信EF中没有包含简单的内部连接,但是我正在映射到DTO,所以我猜这个现在可以使用,直到我查看一些支持过滤的开源包含过滤器。

var rv = context.Users.Include(r => r.AppRoles).ToList().Select(u => new User()
                {
                    UserId = u.UserId,
                    AppRoles = u.AppRoles.Where(x=>x.AppId == 1).ToList()


                });
另一答案

免责声明:我是Entity Framework Plus项目的所有者

EF + Query IncludeFilter允许轻松过滤包含的实体。

public static async Task<List<User>> GetAllAsync()
{
    var rv = new List<User>();

    using (var context = new dbContext())
    {
        rv = await (context.Users.AsNoTracking()
            .IncludeFilter(a => a.AppRoles.Where(a2 => a2.AppId == 1)).ToListAsync());
    }

   return rv;
}

维基:EF+ Query Include Filter

以上是关于如何在EF6.1中过滤掉子集合的主要内容,如果未能解决你的问题,请参考以下文章

Firestore 对集合及其文档的子集合进行过滤

包括过滤器子集合[重复]

如何在 SwiftUI 中使用 Firestore 创建子集合

Firebase Firestore 子集合

如何使用 Flutter 获取 Firestore 中每个集合的子集合

如何从所有文档的子集合中检索所有数据