我有一个泛型类,它使用实体框架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 ;
}
}
}这些接口:
public interface IIdentifyable : IIdentifyable<int>
{
}
public interface IIdentifyable<out TId>
{
TId Id { get; }
}像这样的实体:
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; }
}我的问题是它不编译。我得到了一个错误:
不能将运算符'
==‘应用于'TId’和'TId‘类型的操作数
我试图将它更改为x => Equals(x.Id, id),但是EF无法翻译它。有办法绕过吗?
我知道我可以使用Find()而不是FirstOrDefault。但我需要的不仅仅是上面提到的方法。TId有什么办法可以让EF比较、TId**?**、和,TId目前只有guid和int。我已经看到了下面的问题,但它们没有处理有关将其转换为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'
发布于 2016-10-19 13:45:46
更新:这里的是一种与EF一起工作的简单简洁的方法。
向GenericRepository类添加以下约束
where TId : IEquatable<TId>然后使用Equals方法
x => x.Id.Equals(id);原始答案:
这是一个已知的泛型问题,通常使用EqualityComparer<T>.Default而不是==运算符来处理。但是,这种方法不适用于LINQ实体。
解决这个问题的一种方法是使用来自Expression命名空间的System.Linq.Expressions类动态地构建谓词,如下所示:
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);
}
}像这样使用它:
dbSet.FirstOrDefault(EqualsPredicate(id));或
dbSet.Any(EqualsPredicate(id));等。
发布于 2016-10-19 13:40:02
只有当将TId类型约束为引用类型时,才会进行编译:
public class GenericRepository<TEntity, TId>
where TEntity: class, IIdentifyable<TId>
where TId: class但是,这在您的情况下可能不合适,因此您必须创建不同的类来支持GUID、int或长id值。
https://stackoverflow.com/questions/40132380
复制相似问题