如何通过finder接口在Entity Framework 4中查找实体? (适用于Linq To Sql)

时间:2010-11-04 03:12:16

标签: c# linq linq-to-sql entity-framework

我有一个我的应用程序访问的存储库层,可以用IDataSource初始化;例如LinqToSqlDataSource,EntityFrameworkDataSource等......

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

我的所有基础实体都实现了一个简单的界面,可以通过id通用且方便地查找实体;

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

以下是我在EntityFramework中遇到问题的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);

当上述代码与EntityFramework 4 IDataSource实现一起运行时,会产生以下错误;

无法创建“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 个答案:

答案 0 :(得分:0)

我认为那里的错误在于你试图比较TKey泛型的方式。由于TKey是一种复杂类型,因此必须明确实现==运算符才能进行此比较。现在使用TKey泛型,不能保证它是。也许你可以在TKey上放置另一个通用约束来确保有比较方法可用吗?

答案 1 :(得分:0)

不要问我为什么会这样,但我们设法通过这样做来实现:

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

不知何故,这表现得很好,并编写了正确的SQL WHERE子句。我们尝试的所有其他替代方案都不起作用。