Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将IEqualityComparer与LINQ to Entities Exception子句一起使用_Linq_Linq To Entities_Iequalitycomparer - Fatal编程技术网

将IEqualityComparer与LINQ to Entities Exception子句一起使用

将IEqualityComparer与LINQ to Entities Exception子句一起使用,linq,linq-to-entities,iequalitycomparer,Linq,Linq To Entities,Iequalitycomparer,我有一个实体,我想与子集进行比较,并决定选择除子集以外的所有实体 因此,我的查询如下所示: Products.Except(ProductsToRemove(), new ProductComparer()) public class ProductComparer : IEqualityComparer<Product> { public bool Equals(Product a, Product b) { if (ReferenceEquals

我有一个实体,我想与子集进行比较,并决定选择除子集以外的所有实体

因此,我的查询如下所示:

Products.Except(ProductsToRemove(), new ProductComparer())
public class ProductComparer : IEqualityComparer<Product>
{
    public bool Equals(Product a, Product b)
    {
        if (ReferenceEquals(a, b)) return true;

        if (ReferenceEquals(a, null) || ReferenceEquals(b, null))
            return false;

        return a.Id == b.Id;
    }

    public int GetHashCode(Product product)
    {
        if (ReferenceEquals(product, null)) return 0;
        var hashProductId = product.Id.GetHashCode();
        return hashProductId;
    }
}
public class ProductComparer : IEqualityComparer<Product> {
    private ProductComparer() { }
    public static ProductComparer Instance = new ProductComparer();

    ...
}
ProductsToRemove()
方法在执行一些任务后返回一个
列表。所以最简单的形式是上面的

ProductComparer()
类如下所示:

Products.Except(ProductsToRemove(), new ProductComparer())
public class ProductComparer : IEqualityComparer<Product>
{
    public bool Equals(Product a, Product b)
    {
        if (ReferenceEquals(a, b)) return true;

        if (ReferenceEquals(a, null) || ReferenceEquals(b, null))
            return false;

        return a.Id == b.Id;
    }

    public int GetHashCode(Product product)
    {
        if (ReferenceEquals(product, null)) return 0;
        var hashProductId = product.Id.GetHashCode();
        return hashProductId;
    }
}
public class ProductComparer : IEqualityComparer<Product> {
    private ProductComparer() { }
    public static ProductComparer Instance = new ProductComparer();

    ...
}
公共类ProductComparer:IEqualityComparer
{
公共布尔等于(产品a、产品b)
{
if(ReferenceEquals(a,b))返回true;
if(ReferenceEquals(a,null)| | ReferenceEquals(b,null))
返回false;
返回a.Id==b.Id;
}
public int GetHashCode(产品)
{
if(ReferenceEquals(product,null))返回0;
var hashProductId=product.Id.GetHashCode();
返回hashProductId;
}
}
但是,我不断收到以下例外情况:

LINQ to实体无法识别 方法 'System.Linq.IQueryable
1[UnitedOne.Data.Sql.Product]
除[产品](System.Linq.IQueryable
1[UnitedOne.Data.Sql.Product]外, System.Collections.Generic.IEnumerable
1[UnitedOne.Data.Sql.Product],
System.Collections.Generic.IEqualityComparer
1[UnitedOne.Data.Sql.Product])” 方法,并且此方法不能为空 翻译成商店表达式


您正在尝试将带有自定义
IEqualityComparer
Except
调用转换为实体SQL

显然,您的类不能转换为SQL

您需要编写
Products.AsEnumerable().Except(ProductsToRemove(),new ProductComparer())
以强制在客户端上执行它。请注意,这将从服务器下载所有产品


顺便说一下,您的
ProductComparer
类应该是一个单例,如下所示:

Products.Except(ProductsToRemove(), new ProductComparer())
public class ProductComparer : IEqualityComparer<Product>
{
    public bool Equals(Product a, Product b)
    {
        if (ReferenceEquals(a, b)) return true;

        if (ReferenceEquals(a, null) || ReferenceEquals(b, null))
            return false;

        return a.Id == b.Id;
    }

    public int GetHashCode(Product product)
    {
        if (ReferenceEquals(product, null)) return 0;
        var hashProductId = product.Id.GetHashCode();
        return hashProductId;
    }
}
public class ProductComparer : IEqualityComparer<Product> {
    private ProductComparer() { }
    public static ProductComparer Instance = new ProductComparer();

    ...
}
公共类ProductComparer:IEqualityComparer{
私有ProductComparer(){}
公共静态ProductComparer实例=新ProductComparer();
...
}

IEqualityComparer
只能在本地执行,不能转换为SQL命令,因此错误

Linq to Entities实际上不是执行查询,而是解释代码,将其转换为TSQL,然后在服务器上执行

在封面下,它被编码为运算符和常用函数如何操作以及它们如何与TSQL相关的知识。问题是L2E的开发人员不知道您是如何实现IEqualityComparer的。因此,他们无法理解,当你说
classa==classb
时,你的意思是(例如)
“Where Person.FirstName==FirstName和Person.LastName==LastName”

因此,当L2E解释器遇到它无法识别的方法时,它会抛出此异常

有两种方法可以解决这个问题。首先,开发一个
Where()
,它满足您的平等性要求,但不依赖于任何自定义方法。换句话说,测试实例属性的相等性,而不是类上定义的
Equals
方法

其次,您可以触发查询的执行,然后在内存中进行比较。例如:

var notThisItem = new Item{Id = "HurrDurr"};
var items = Db.Items.ToArray(); // Sql query executed here
var except = items.Except(notThisItem); // performed in memory

显然,这将带来更多的数据通过电线和更多的内存密集。第一种选择通常是最好的。

谢谢你的建议。在这种情况下,我们只讨论了不到100行,所以我认为第二种选择没有那么糟糕。我可能缓存结果只是为了加快未来的搜索速度。谢谢除了
ToArray
之外,您还可以使用
AsEnumerable
,它也将在内存中执行,但不需要在开始处理之前将数据库中的所有内容加载到内存中。这会有很大的不同。嘿,Slaks,你能详细介绍一下使用IEqualityComparer作为singleton吗?性能方面还是其他原因?因为我很难找到IEqualityComparer作为singleton的示例,即使在MSDN文档中也是如此。@Mare:因为各个实例之间没有区别,所以拥有多个实例是没有意义的。