首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >EF -不能将运算符'==‘应用于'TId’和'TId‘类型的操作数。

EF -不能将运算符'==‘应用于'TId’和'TId‘类型的操作数。
EN

Stack Overflow用户
提问于 2016-10-19 13:11:16
回答 2查看 1.8K关注 0票数 15

我有一个泛型类,它使用实体框架6.x。

代码语言:javascript
复制
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 ;
        }
    }
}

这些接口:

代码语言:javascript
复制
public interface IIdentifyable : IIdentifyable<int>
{
}

public interface IIdentifyable<out TId>
{
    TId Id { get; }
}

像这样的实体:

代码语言:javascript
复制
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目前只有guidint。我已经看到了下面的问题,但它们没有处理有关将其转换为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'

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-10-19 13:45:46

更新:这里的是一种与EF一起工作的简单简洁的方法。

GenericRepository类添加以下约束

代码语言:javascript
复制
where TId : IEquatable<TId>

然后使用Equals方法

代码语言:javascript
复制
x => x.Id.Equals(id);

原始答案:

这是一个已知的泛型问题,通常使用EqualityComparer<T>.Default而不是==运算符来处理。但是,这种方法不适用于LINQ实体。

解决这个问题的一种方法是使用来自Expression命名空间的System.Linq.Expressions类动态地构建谓词,如下所示:

代码语言:javascript
复制
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);
    }
}

像这样使用它:

代码语言:javascript
复制
dbSet.FirstOrDefault(EqualsPredicate(id));

代码语言:javascript
复制
dbSet.Any(EqualsPredicate(id));

等。

票数 19
EN

Stack Overflow用户

发布于 2016-10-19 13:40:02

只有当将TId类型约束为引用类型时,才会进行编译:

代码语言:javascript
复制
public class GenericRepository<TEntity, TId> 
    where TEntity: class, IIdentifyable<TId> 
    where TId: class

但是,这在您的情况下可能不合适,因此您必须创建不同的类来支持GUID、int或长id值。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40132380

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档