在使用EF的泛型参数上使用Equals时出错 [英] Getting errors when using Equals on generic parameters with EF
问题描述
我有以下两个泛型类:
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屋!