简体   繁体   English

在EF的通用参数上使用Equals时出错

[英]Getting errors when using Equals on generic parameters with EF

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. 我的问题是Get方法。 I keep getting this error 我不断收到这个错误

Unable to create a constant value of type 'System.Object'. 无法创建类型为'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 不能将==应用于操作数TKey和TKey

Why isnt this working? 为什么这不起作用? my TKey is supposed to be a primitive data type, isnt the limiter where TKey:struct the correct one? 我的TKey应该是原始数据类型,不是TKey:struct正确的限制器吗?

Why is the compiler using Equals(object) when there is Equals(int), which is what this key is? 为什么在有Equals(int)的情况下,编译器为什么使用Equals(object)?

The == comparison fails because that operator can only be used for predefined value types or for reference types, and your TKey is neither. ==比较失败,因为该运算符只能用于预定义的值类型或引用类型,而您的TKey都不可用。

You say in your comment that TKey is an int . 您在评论中说TKey是一个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 . 您的情况下可能是对 ,但是您的类的用户可以定义Entity<List<string>.Enumerator>因为List<T>.Enumeratorstruct 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 . 我的观点是,编译器在编译时无法知道除了使用object.Equals之外该如何做。

I wonder why you're constraining the key type to be a struct anyway. 我不知道为什么您无论如何都要限制键类型为struct The most common types of ID that I've seen are int and string . 我见过的最常见的ID类型是intstring By using a struct you're already ruling out string ... 通过使用struct您已经排除了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. 更新 :您可以限制TKey使其实现IComparable ,因为所有数字类型都可以实现。 That would then let you use CompareTo within the implementation of your Get method. 然后,您可以在Get方法的实现中使用CompareTo

However, since the lambda you pass to FirstOrDefault will actually be executed on the database side, I'm not sure what will happen, ie whether EF will be able to translate that to a SQL expression correctly. 但是,由于传递给FirstOrDefault的lambda实际上将在数据库端执行,因此我不确定会发生什么,即EF是否能够将其正确转换为SQL表达式。

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

You could simply use the IDbSet.Find method, which takes one or more object -typed key values. 您可以简单地使用IDbSet.Find方法,该方法采用一个或多个object类型的键值。

public TEntity Get(TKey key)
{               
    return Set.Find(key);
}

This has the additional advantage that it's more efficient if the entity already exists in the DbContext 's local cache (since it avoids an unnecessary trip to the database). 这样做还有一个好处,就是如果该实体已经存在于DbContext的本地缓存中,则效率更高(因为它避免了不必要的数据库访问)。

However, I suspect you're going to want to do more than just retrieve individual items, so you'll probably run into the same problem later. 但是,我怀疑您将要做的不仅仅是检索单个项目,因此以后您可能会遇到相同的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM