通过LINQ筛选包含ICollection属性的查询

本文关键字:属性 查询 ICollection 包含 LINQ 筛选 通过 | 更新日期: 2023-09-27 18:07:47

我有2个模型:ApplicationUser和TaskModel

public class ApplicationUser : IdentityUser
{
     public virtual ICollection<TaskModel> Tasks { get; set; }
     ...
}

public class TaskModel
{
     public virtual ICollection<ApplicationUser> Managers { get; set; }
     ...
}

我想从数据库中只选择包含一些applicationuser对象在管理器中的记录。然后我尝试使用LINQ

ApplicationUser currentUser = "SomeObject";
var taskModels = db.Tasks.Where(t => t.Managers.Contains(currentUser)).Include(t => t.Autor);

但是Where子句产生了错误。错误信息显示"无法创建一个常量"。ApplicationUser"类型。在这种情况下,它只支持基本类型和枚举类型。"我通过下一个代码

得到我需要的
var allTasks = db.Tasks.Include(t => t.Autor).ToList();
List<TaskModel> filterTasks = new List<TaskModel>();
foreach (var task in allTasks)
{
   if (task.Managers.Contains(currentUser))
       filterTasks.Add(task);
}
return View(filterTasks);

但是我想知道如何通过LINQ语法解决

通过LINQ筛选包含ICollection属性的查询

尝试使用可以指定要比较的列的Any方法,例如:

var taskModels = db.Tasks
                   .Where(t => t.Managers.Any(m => m.Id == currentUser.Id))
                   .Include(t => t.Autor) 
                   .ToList();

不要忘记调用一个方法来执行这个语句,比如ToList()FirstOrDefault()

你不能使用Contains与你的ApplicationUser实例,因为查询是由LINQ到SQL执行(或LINQ到实体,如果你使用实体框架),显然你的数据库不知道你的ApplicationUser类。

你的第二种方法是有效的,因为在调用ToList()之后,剩余的代码由LINQ to Objects执行。它等于下面的语句:

db.Tasks.Include(t => t.Autor).ToList().Where(t => t.Managers.Contains(currentUser)).ToList();

注意在Include之后附加的ToList()。然而,如果你有很多任务,这可能会执行得很差,因为所有的任务都是从数据库中获取的,然后才进行过滤。

您应该尝试使用@FelipeOriani所示的方法,因为在这种情况下,只从数据库中获取相关的任务。