【问题标题】:Exclude collection for removal, Linq排除要删除的集合,Linq
【发布时间】:2017-06-15 11:49:18
【问题描述】:

我试图让 except 方法像这个答案一样工作: https://stackoverflow.com/a/3944821/169714

第一次尝试:

var housesToRemove = db.Houses.Except(houses).ToList();

第二次尝试:

var housesToRemove = db.Houses.Where(h => 
     !houses.Any(h2 => h2.Code.Equals(h.Code) && h2.OperatorId == h.OperatorId)).ToList();

我的 Houses 类已覆盖 Equals:

public override bool Equals(object obj)
{
    var item = obj as House;

    if (item == null)
        return false;

    return this.Code == item.Code && this.OperatorId == item.OperatorId;
}

public override int GetHashCode()
{
    return this.ID.GetHashCode();
}

两个选项都抛出:

System.NotSupportedException: '无法创建'House' 类型的常量值。此上下文仅支持原始类型或枚举类型。'

我使用它的部分代码:

using (var db = new HouseContext())
{
    var housesToRemove = db.Houses.Where(h => !houses.Any(h2 => h2.Code.Equals(h.Code) && h2.OperatorId == h.OperatorId)).ToList();

    foreach (var htr in housesToRemove)
    {
        Console.WriteLine(htr); // I have also overwritten ToString() from House
    }
    housesToRemove.ForEach(x => x.IsListed = false);
    db.SaveChanges();
}

【问题讨论】:

    标签: c# linq except


    【解决方案1】:

    您链接的问题是使用 Linq to Entities 而您正在使用 Linq to SQL 这意味着您的 Except 查询正在发送到数据库.数据库不知道您在此处实际尝试执行的操作。

    我建议您按照此处的答案进行操作:https://stackoverflow.com/a/18944508/639771,以获取有关失败原因以及解决方法的更多信息。

    tl;dr

    您正在尝试将内存中的对象与数据库对象进行比较,因为 SQL 引擎并不关心您的 Equals 覆盖,它所看到的只是内存中的 House 对象和对它的数据库的调用不知何故必须能够通过进行比较。您可以改为取消您不想要的房屋的 ID,然后执行以下操作:

    var ids = houses.Select(h => h.Id).ToArray();
    var filtered = db.Houses.Where(h => !ids.Contains(h.Id)).ToList();
    

    【讨论】:

    • 谢谢,我认为 Linq (db.Houses) 有一个内存中所有内容的内部列表。
    • @JPHellemons 不,实际上比这更疯狂。这一切都基于IQueryable,它采用LINQ 表达式并将它们转换为SQL 语句,然后将其发送到数据库。这样您就可以在数百万行的表中进行搜索,而无需先加载所有数据。
    猜你喜欢
    • 2010-12-05
    • 1970-01-01
    • 2014-03-08
    • 2011-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多