EF - 不能将运算符'=='应用于'TId'和'TId'类型的操作数 [英] EF - Cannot apply operator '==' to operands of type 'TId' and 'TId'
问题描述
public class GenericRepository< TEntity,TId>< p>我有这个通用类,它使用实体框架6.x。其中TEntity,class,IIdentifyable< TId>
{
public virtual TEntity GetById(TId id)
{
using(var context = new DbContext())
{
var dbSet = context。设置< TEntity>();
var currentItem = dbSet.FirstOrDefault(x => x.Id == id);
返回currentItem;
public virtual bool Exists(TId id)
{
using(var context = new DbContext())
{
var dbSet = context.Set< TEntity>();
var exists = dbSet.Any(x => x.Id == id);
return存在;
}
}
}
p>
public interface IIdentifyable:IIdentifyable< int>
{
}
public interface IIdentifyable< out TId>
{
TId Id {get; }
}
看起来像这样的实体:
public class CustomerEntity:IIdentifyable< int>
{
public string Name {get;组; }
public int Id {get; set; }
}
public class ProductEntity:IIdentifyable< Guid>
{
public string Name {get;组; }
public Guid Id {get; set; }
}
我的问题是它不能编译。我得到这个错误:
无法应用运算符'
==
'到'TId
'和'TId
'的操作数
我试图将它更改为 x => Equals(x.Id,id)
,但EF无法翻译它。任何方式吗?
我知道我可以使用 Find()
而不是 FirstOrDefault
。但我比上面提到的方法更需要这个。 有什么方法可以让EF比较 TId
和 TId
? <$ c $目前只有 guid
和 int
。我已经看到了下面的问题,但他们没有处理有关转换为SQL的问题。
这是一个泛型的已知问题,通常使用 EqualityComparer< T> .Default
来代替 ==
运算符。然而,这种方法不适用于LINQ to Entities。
解决这个问题的一种方法是使用 Expression
System.Linq.Expressions
命名空间中的类>:
$ b
public class GenericRepository< TEntity,TId>其中TEntity:class,IIdentifyable< TId>
{
protected static Expression< Func< TEntity,bool>> EqualsPredicate(TId id)
{
表达式< Func< TEntity,TId>> selector = x => x.Id;
Expression< Func< TId>> closure =()=> ID;
return Expression.Lambda< Func< TEntity,bool>>(
Expression.Equal(selector.Body,closure.Body),
selector.Parameters);
$ / code $ / pre
并像这样使用它:
dbSet.FirstOrDefault(EqualsPredicate(id));
或
dbSet.Any(EqualsPredicate(ID));
等。
更新:这是另一种适用于EF的方式。
将以下约束添加到 GenericRepository
类
其中TId:IEquatable< TId>
,然后使用等于
方法
x => x.Id.Equals(ID);
I have this generic class, which uses Entity Framework 6.x.
public class GenericRepository<TEntity, TId> where TEntity, class, IIdentifyable<TId>
{
public virtual TEntity GetById(TId id)
{
using (var context = new DbContext())
{
var dbSet = context.Set<TEntity>();
var currentItem = dbSet.FirstOrDefault(x => x.Id == id);
return currentItem;
}
}
public virtual bool Exists(TId id)
{
using (var context = new DbContext())
{
var dbSet = context.Set<TEntity>();
var exists = dbSet.Any(x => x.Id == id);
return exists ;
}
}
}
And these interfaces:
public interface IIdentifyable : IIdentifyable<int>
{
}
public interface IIdentifyable<out TId>
{
TId Id { get; }
}
And entities that looks like this:
public class CustomerEntity : IIdentifyable<int>
{
public string Name { get; set; }
public int Id { get;set; }
}
public class ProductEntity : IIdentifyable<Guid>
{
public string Name { get; set; }
public Guid Id { get;set; }
}
My issue is that it doesn't compile. I get this error:
Cannot apply operator '==
' to operands of type 'TId
' and 'TId
'
I tried to change it to x => Equals(x.Id, id)
, but then EF cannot translate it. Any way around it?
I know that I can use Find()
instead of FirstOrDefault
. But I need this for more than the methods mentioned above. Is there any way I can let EF compare TId
with TId
? TId
is currently only guid
and int
. I've already seen the questions below, but they don't handle the issue regarding translation to SQL.
Can't operator == be applied to generic types in C#?
How to solve Operator '!=' cannot be applied to operands of type 'T' and 'T'
解决方案 This is a known issue with generics which normally is handled by using EqualityComparer<T>.Default
instead of the ==
operator. However this approach doesn't work with LINQ to Entities.
One way to solve it is to build the predicate dynamically using the Expression
class from the System.Linq.Expressions
namespace like this:
public class GenericRepository<TEntity, TId> where TEntity: class, IIdentifyable<TId>
{
protected static Expression<Func<TEntity, bool>> EqualsPredicate(TId id)
{
Expression<Func<TEntity, TId>> selector = x => x.Id;
Expression<Func<TId>> closure = () => id;
return Expression.Lambda<Func<TEntity, bool>>(
Expression.Equal(selector.Body, closure.Body),
selector.Parameters);
}
}
and use it like this:
dbSet.FirstOrDefault(EqualsPredicate(id));
or
dbSet.Any(EqualsPredicate(id));
etc.
Update: Here is another way that works with EF.
Add the following constraint to the GenericRepository
class
where TId : IEquatable<TId>
and then use Equals
method
x => x.Id.Equals(id);
这篇关于EF - 不能将运算符'=='应用于'TId'和'TId'类型的操作数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!