在使用EF的泛型参数上使用Equals时出错 [英] Getting errors when using Equals on generic parameters with EF

查看:189
本文介绍了在使用EF的泛型参数上使用Equals时出错的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下两个泛型类:

  public abstract class Entity< T> :IEntity< T>,IAuditableEntity,ISoftDeletable其中T:struct 
{
public T Id {get;组; }
public DateTime CreatedDate {get;组; }
public string CreatedBy {get;组; }
public DateTime UpdatedDate {get;组; }
public string UpdatedBy {get;组; }
public bool已删除{get;组; }
}


公共抽象类存储库< TEntity,TKey> :IRepository< TEntity,TKey>其中TEntity:实体< TKey> TKey:struct
{
protected DbContext Context;
只读保护IDbSet< TEntity>组;

受保护的库(DbContext上下文)
{
上下文=上下文;
Set = Context.Set< TEntity>();
}

public TEntity Get(TKey key)
{
var output = Set.FirstOrDefault(o => o.Id.Equals(key));
返回输出;
}
}

我的问题是Get方法。我一直收到这个错误


无法创建类型为System.Object的常量值。


我试过使用==但它不会编译并说


无法将==应用于操作数TKey和TKey


为什么没有这个工作?我的TKey应该是一个原始数据类型,而不是TKey:构造正确的限制器?



为什么是编译器在Equals(int)时使用Equals(object),这就是这个键的作用么? <$> <$> <$> c $ c> == 比较失败,因为该运算符只能用于预定义的值类型或引用类型,并且您的 TKey 既不是。

您在评论中说 TKey int 在你的 情况下可能是真的,但是你的类的用户可以定义一个实体< List< string> .Enumerator> 列出< T> .Enum erator struct 。我的观点是编译器无法知道,在编译时

,除了使用 object.Equals



以外,如何做其他任何事情。我想知道为什么你要限制密钥类型无论如何,它都是一个 struct 。我见过的最常见的ID类型是 int string 。通过使用 struct ,您已经排除了 string ...



你是否真的需要灵活性来支持不是整数的键?如果没有,您的类可能会更简单。






更新:您可以限制 TKey ,因为它实现了 IComparable ,因为所有的数字类型都实现了这个功能。然后,您可以在 Get 方法的实现中使用 CompareTo



但是,由于传递给 FirstOrDefault 的lambda实际上将在数据库端执行,所以我不确定会发生什么,即EF是否会能够正确地将其转换为SQL表达式。

  public abstract class实体< T> :IEntity< T>,IAuditableEntity,ISoftDeletable其中T:struct,IComparable 

public abstract class Repository< TEntity,TKey> :IRepository< TEntity,TKey>其中TEntity:实体< TKey> TKey:struct,IComparable


I have the following two generic classes:

 public abstract class Entity<T> : IEntity<T>, IAuditableEntity,ISoftDeletable where T : struct
    {
        public T Id { get; set; }
        public DateTime CreatedDate { get; set; }
        public string CreatedBy { get; set; }
        public DateTime UpdatedDate { get; set; }
        public string UpdatedBy { get; set; }
        public bool Deleted { get; set; }
    }


    public abstract class Repository<TEntity,TKey> : IRepository<TEntity, TKey> where TEntity :Entity<TKey> where TKey : struct           
    {
        protected DbContext Context;
        protected readonly IDbSet<TEntity> Set;

        protected Repository(DbContext context)
        {
            Context = context;
            Set = Context.Set<TEntity>();
        }

        public TEntity Get(TKey key)
        {               
            var output = Set.FirstOrDefault(o => o.Id.Equals(key));
            return output ;
        }
    }

My problem is the Get method. I keep getting this error

Unable to create a constant value of type 'System.Object'. Only primitive types or enumeration types are supported in this context."

i tried to use == but it wont compile and says

cannot apply == to operands TKey and TKey

Why isnt this working? my TKey is supposed to be a primitive data type, isnt the limiter where TKey:struct the correct one?

Why is the compiler using Equals(object) when there is Equals(int), which is what this key is?

解决方案

The == comparison fails because that operator can only be used for predefined value types or for reference types, and your TKey is neither.

You say in your comment that TKey is an int. That may be true in your case, but a user of your class(es) could define an Entity<List<string>.Enumerator> since List<T>.Enumerator is a struct. The mind boggles at what "equals" means in that case.

My point is that the compiler has no way to know, at compile time, how to do anything other than use object.Equals.

I wonder why you're constraining the key type to be a struct anyway. The most common types of ID that I've seen are int and string. By using a struct you're already ruling out string...

Do you really need the flexibility to support keys that are not integers? If not, your classes could be much simpler.


Update: you could constrain your TKey such that it implements IComparable, since all the numeric types implement that. That would then let you use CompareTo within the implementation of your Get method.

However, since the lambda you pass to FirstOrDefault will actually be executed on the database side, I'm not sure what will happen, i.e. whether EF will be able to translate that to a SQL expression correctly.

public abstract class Entity<T> : IEntity<T>, IAuditableEntity,ISoftDeletable where T : struct, IComparable

public abstract class Repository<TEntity,TKey> : IRepository<TEntity, TKey> where TEntity :Entity<TKey> where TKey : struct, IComparable

这篇关于在使用EF的泛型参数上使用Equals时出错的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆