Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/266.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# EF-无法应用运算符'==';到类型为'的操作数;工业贸易署';和';工业贸易署';_C#_Entity Framework_Generics - Fatal编程技术网

C# EF-无法应用运算符'==';到类型为'的操作数;工业贸易署';和';工业贸易署';

C# EF-无法应用运算符'==';到类型为'的操作数;工业贸易署';和';工业贸易署';,c#,entity-framework,generics,C#,Entity Framework,Generics,我有一个通用类,它使用EntityFramework 6.x public class GenericRepository<TEntity, TId> where TEntity, class, IIdentifyable<TId> { public virtual TEntity GetById(TId id) { using (var context = new DbContext()) { va

我有一个通用类,它使用EntityFramework 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 ;
        }
    }
}
公共类通用存储,其中tenty、class、i可识别
{
公共虚拟用户id(TId id)
{
使用(var context=new DbContext())
{
var dbSet=context.Set();
var currentItem=dbSet.FirstOrDefault(x=>x.Id==Id);
返回当前项目;
}
}
存在公共虚拟bool(TId id)
{
使用(var context=new DbContext())
{
var dbSet=context.Set();
var exists=dbSet.Any(x=>x.Id==Id);
回报存在;
}
}
}
这些接口:

public interface IIdentifyable : IIdentifyable<int>
{
}

public interface IIdentifyable<out TId>
{
    TId Id { get; }
}
公共接口可识别:可识别
{
}
可识别的公共接口
{
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; }
}
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));
公共类客户属性:可识别
{
公共字符串名称{get;set;}
公共int Id{get;set;}
}
公共类ProductEntity:可识别
{
公共字符串名称{get;set;}
公共Guid Id{get;set;}
}
我的问题是它无法编译。我收到以下错误:

无法将运算符“
=
”应用于“
TId
”和“
TId
”类型的操作数

我试图将其更改为
x=>Equals(x.Id,Id)
,但EF无法翻译它。有办法吗

我知道我可以使用
Find()
而不是
FirstOrDefault
。但是我需要的不仅仅是上面提到的方法我有没有办法让EF将
TId
TId
进行比较?
TId
目前只有
guid
int
。我已经看到了下面的问题,但它们没有处理有关转换为SQL的问题


仅当您将
TId
类型约束为引用类型时,此选项才编译:

public class GenericRepository<TEntity, TId> 
    where TEntity: class, IIdentifyable<TId> 
    where TId: class
公共类通用存储库
其中tenty:类,可识别
TId:class在哪里

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

更新:以下是一种简单简洁的方法,可用于EF

将以下约束添加到
GenericRepository

where TId : IEquatable<TId>

原始答案:

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

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

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; }
}
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));


等等。

那么从你链接的答案来看,你为什么不设置TId:class?TId不是类就是结构,c#不能tell@misha130-因为
int
不是
。int在c#@misha130中是一个名为Int32的类,它不是,它是一个名为
Int32
的结构。是的,Magnus是对的,即使我添加
struct
约束,它也不会编译。谢谢。这确实可以解决问题。但是,由于我实际上想使用
int
作为Id,所以实现起来会有问题。当你说“这是一个已知的问题”时,你有任何参考资料吗?@HANDL,每个尝试它的人都知道,因为编译器错误:),原因是
==
运算符并没有为每种类型定义,这在本文中进行了解释。以及缺少通用运算符约束。但你是对的,可能我用了不正确的措辞。你的措辞没有错,只是我问了一个类似的问题,因为我不敢相信这是行不通的。但是Eric Lippert已经用一种可以接受的方式表述了这一点。“更新”中非常简洁的解决方案是确定的,应该在原始答案文本之上突出显示。这是一个非常好且简单的解决方案!