繁体   English   中英

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

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

我有以下两个通用类:

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

我的问题是Get方法。 我不断收到这个错误

无法创建类型为'System.Object'的常量值。 在这种情况下,仅支持原始类型或枚举类型。”

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

不能将==应用于操作数TKey和TKey

为什么这不起作用? 我的TKey应该是原始数据类型,不是TKey:struct正确的限制器吗?

为什么在有Equals(int)的情况下,编译器为什么使用Equals(object)?

==比较失败,因为该运算符只能用于预定义的值类型或引用类型,而您的TKey都不可用。

您在评论中说TKey是一个int 您的情况下可能是对 ,但是您的类的用户可以定义Entity<List<string>.Enumerator>因为List<T>.Enumeratorstruct 在这种情况下,头脑会困惑于“相等”的含义。

我的观点是,编译器在编译时无法知道除了使用object.Equals之外该如何做。

我不知道为什么您无论如何都要限制键类型为struct 我见过的最常见的ID类型是intstring 通过使用struct您已经排除了string ...

您是否真的需要灵活性来支持非整数键? 如果没有,您的课程可能会简单得多。


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

但是,由于传递给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

您可以简单地使用IDbSet.Find方法,该方法采用一个或多个object类型的键值。

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

这样做还有一个好处,就是如果该实体已经存在于DbContext的本地缓存中,则效率更高(因为它避免了不必要的数据库访问)。

但是,我怀疑您将要做的不仅仅是检索单个项目,因此以后您可能会遇到相同的问题。

暂无
暂无

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

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