smo*_*nes 12 c# generics entity-framework
我有这个泛型类,它使用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 ;
}
}
}
Run Code Online (Sandbox Code Playgroud)
这些接口:
public interface IIdentifyable : IIdentifyable<int>
{
}
public interface IIdentifyable<out TId>
{
TId Id { get; }
}
Run Code Online (Sandbox Code Playgroud)
和看起来像这样的实体:
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; }
}
Run Code Online (Sandbox Code Playgroud)
我的问题是它没有编译.我收到此错误:
不能将运算符'
=='应用于'TId'和'TId' 类型的操作数
我试图将其更改为x => Equals(x.Id, id),但EF无法翻译它.有什么办法吗?
我知道我可以用Find()而不是FirstOrDefault.但我需要的不仅仅是上面提到的方法.有没有什么办法可以让EF比较TId有TId? TId目前只有guid和int.我已经看过下面的问题了,但他们没有处理有关转换为SQL的问题.
Iva*_*oev 13
这是泛型的已知问题,通常通过使用GenericRepository而不是Equals运算符来处理.但是,这种方法不适用于LINQ to Entities.
解决它的一种方法是使用命名空间中的EqualityComparer<T>.Default类动态构建谓词,==如下所示:
where TId : IEquatable<TId>
Run Code Online (Sandbox Code Playgroud)
并像这样使用它:
x => x.Id.Equals(id);
Run Code Online (Sandbox Code Playgroud)
要么
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);
}
}
Run Code Online (Sandbox Code Playgroud)
等等
更新:这是另一种适用于EF的方式.
将以下约束添加到Expression类中
dbSet.FirstOrDefault(EqualsPredicate(id));
Run Code Online (Sandbox Code Playgroud)
然后使用System.Linq.Expressions方法
dbSet.Any(EqualsPredicate(id));
Run Code Online (Sandbox Code Playgroud)