将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.IQueryable1[UnitedOne.Data.Sql.Product]
除[产品](System.Linq.IQueryable
1[UnitedOne.Data.Sql.Product]外,
System.Collections.Generic.IEnumerable1[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:因为各个实例之间没有区别,所以拥有多个实例是没有意义的。