Linq表达式不允许通用属性类型

时间:2017-02-21 19:23:57

标签: c# .net linq generics

  

错误:无法创建类型' System.Object'的常量值。在此上下文中仅支持原始类型或枚举类型。

好的,这是交易, 我有一个通用基本实体,如下所示:

public abstract class Entity<Tkey> : IEntity<Tkey>
    where Tkey:IComparable
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public abstract Tkey Id { get; set;}

}

我更喜欢这个,因为你知道,一些表的Identity列类型是Guid,有些是int,有些是long。

所以,在我的Generic存储库中,我有一些像这样的方法:

public class FRepository<TEntity,Tkey>:IDisposable where TEntity : Entity<Tkey>, new()
    where Tkey:IComparable

{

    public TEntity Find(Tkey id)
    {
        return this.GetAll().Where(e=> e.Id.CompareTo(id)==0).FirstOrDefault();
    }
}

GetAll()方法返回IQueryable<TEntity>.

但是当我使用Linq查找特定实体时,它会在我写这篇文章的开头时抛出异常。

注意:我想要查找的实体具有带int类型的Id,因此它是原始类型...

注意事项1:我无法使用&#39; ==&#39;具有泛型TKey的运算符。我收到编译错误。

注意事项2:我也试过这个Where(e=>e.Id.GetHashCode()==id.GetHashCode())。这会引发另一个错误(运行时)。

  

LINQ to Entities无法识别方法&#39; Int32 GetHashCode()&#39;方法,并且此方法无法转换为商店表达式。

1 个答案:

答案 0 :(得分:2)

而不是尝试解决原始问题,因为其他一些用户已经注释到并非所有有效的表达式都可以翻译成SQL,我会尝试给你一些建议......

要点:

  • 您希望Id实施IEquatable<TId>,而不是IComparable<TId>。因此,您将能够编写如下类型的类型:id.Equals(id2)。 BTW EF也无法处理IEquatable<T>.Equals(请参阅Is it possible to use IComparable to compare entities in Entity Framework?)。无论如何,你不会再去这条路了,但建议仍然有效,你需要IEquatable<T>,而不是比较。 请参阅下一点,了解原因
  • 您不希望在您的存储库中使用GetAll方法,以便以后Id 查找实体。对于这个确切的用例,实体框架已经有IDbSet<T>.Find method

另外,我建议您阅读我在2011年(很久以前)在存储库中对GetAll撰写的一些答案:Repository design pattern。另外,我已经记录了存储库模式here,我在其中解释了对GetAll的反对意见。