代码之家  ›  专栏  ›  技术社区  ›  Joshua Hayes

如何通过finder接口在EntityFramework4中查找实体?(在Linqtosql工作)

  •  2
  • Joshua Hayes  · 技术社区  · 14 年前

    我有一个存储库层,我的应用程序可以使用 IDataSource ;例如linqtosqldatasource、entityframeworkdatasource等…

    IDataSource分别提供插入、更新、删除和查询数据源的方法。与这个问题相关的是 FindAll<T> 返回一个 IQueryable<T> .

    我的所有基本实体都实现了一个简单的接口,使按id查找实体通用方便;

    public interface IAmIdentifiable<T>
    {
        T Id { get; set; }
    }
    

    下面是 FindById<T, TKey> 方法我在实体框架中遇到问题。

    public class Repository
    {
        public Repository(IDataSource dataSource)
        {...}
    
        public T FindById<T, TKey>(TKey identifier) where T : class, IAmIdentifiable<TKey>
        {
            return _DataSource.FindAll<T>().SingleOrDefault(i => i.Id.Equals(identifier));
        }
    
        ...
    }
    

    这个 FindById<T, Tkey>(...) 可以与linqtosql一起使用,但不能在entityframework 4中使用 .

    示例用法

    User user = Repository.FindById<User, int>(someUserId);
    Message msg = Repository.FindById<Message, Guid>(someMessageId);
    

    当上面的代码与EntityFramework4IDataSource实现一起运行时,会产生以下错误:

    无法创建“system.object”类型的常量值。在此上下文中仅支持基元类型(如int32、string和guid)。

    我已经尝试更改此项以对值类型执行一个==比较。我了解到,将泛型约束到值类型的迂回方法是 struct . 我已经更新了所有实体的基本接口和相应的存储库查找程序…

    public interface IAmIdentifiable<T> where T : struct
    {
        T Id { get; set; }
    }
    
    public T FindById<T, TKey>(TKey identifier)
        where T : class, IAmIdentifiable<TKey>
        where TKey : struct
    {
        return _DataSource.FindAll<T>().SingleOrDefault(i => i.Id == identifier);
    }
    

    但是这仍然会导致编译错误;

    错误59运算符“==”不能应用于“tkey”和“tkey”类型的操作数

    有谁能解释一下我如何把这些实体 IAmIdentifiable<T> 接口,以便具有按ID检索实体的通用方法?

    2 回复  |  直到 14 年前
        1
  •  0
  •   Slappy    14 年前

    我认为错误在于您试图比较tkey generic的方式。由于Tkey是一个复杂类型,因此必须显式实现==运算符才能进行此比较。现在使用tkey generic,并不能保证它是通用的。也许您可以在tkey上放置另一个通用约束,以确保存在可用的比较方法?

        2
  •  0
  •   Joe Enos    12 年前

    别问我为什么这样做,但我们设法做到了:

    i => (object)i.Id == (object)identifier
    

    不知怎的,这表现得很好,并编写了正确的sql WHERE 条款。我们尝试的其他选择都不起作用。