如何通过finder接口在EntityFramework 4中查找实体? (适用于LinqToSql)

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

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

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

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

下面是我在EntityFramework中遇到问题的FindById方法的相关代码。

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

这个FindById(...) 适用于LinqToSql,但在EntityFramework 4中不起作用

用法示例

 User user = Repository.FindById(someUserId); Message msg = Repository.FindById(someMessageId); 

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

无法创建“System.Object”类型的常量值。 在此上下文中仅支持基本类型(例如Int32,String和Guid’)。

我试过更改它来对值类型执行==比较。 我读到了将generics约束为值类型的一种迂回方式是约束struct 。 我相应更新了所有实体和存储库查找器的基本接口…

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

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

错误59运算符’==’无法应用于’TKey’和’TKey’类型的操作数

任何人都可以了解我如何将这些实体转换为IAmIdentifiable接口,以便通过Id检索实体的通用方法?

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

不要问我为什么会这样,但我们设法通过以下方式实现:

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

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