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:
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'类型的操作数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!