2010-08-07 26 views
3

所以我试图创建一个通过ID方法为基础存储库类的通用选择。为了达到这个目的,我使用了POCO的EF4。我创建了一个名为Id的getter接口,并成功修改了T4模板,以便在返回PK的所有实体中都有一个通用的Id属性。在EF4中通过ID选择通用存储库

问题出在我使用查询时。我采取这样的:

public virtual T GetByID(int id) 
{ 
    return Database.ObjectSet<T>().SingleOrDefault(entity => entity.Id == id); 
} 

而且即使在对象集返回的所有实体具有Id属性与他们当前的主键值设置,我发现了一个奇怪的错误:

The specified type member 'Id' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported.

我错过了什么吗?

回答

3

如果只有泛型Id(如你所说)“返回PK”但实际上并没有映射到PK本身,那么EF就无法将它转换为SQL查询。

过去我用过的一种模式:如果所有的实体都有一个名为Id的int PK,那么你可以让它们都从某个基类继承而来,其中的Id属性被定义(映射到),然后请在您的通用方法中添加where子句:

public virtual T GetByID(int id) where T : EntityBaseClass 

仅供参考,我也将此用于具有使用泛型的不同类型PK的实体。

+0

Id的吸气矿库返回的PK是映射实体的财产。另外,ObjectSet ()方法具有以下签名。 public virtual IObjectSet ObjectSet ()其中T:class,IEntity。 IEntity是映射我所有实体PK的接口。 – 2010-08-08 06:11:46

+1

正如我所提到的,如果ID是返回PK的属性,但未映射,EF应如何知道如何生成查询?就EF而言,这不是映射到DB,也不能被查询!您需要针对映射的属性本身进行查询,该解决方案是使用基类。另外,如果你映射实际的ID属性(而不是仅仅从getter中返回PK),那也可以。 – hackerhasid 2010-08-08 12:26:17

+0

感谢您的评论和答复。 – 2010-08-08 22:22:22

1

我不知道。我认为

public virtual T GetByID(int id) 

这是一个坏主意,因为它是一个硬编码。 如果我有一个guid键的实体会怎么样?

为STE实体

public interface IRepository<TE, TK> 
    where TE : class, IEntityId<TK>, new() 
    where TK : struct 
{ 
    IQueryable<TE> Query(); 
    IQueryable<TE> Query(Expression<Func<TE, Object>> includeExpression); 
    IQueryable<TE> Query(IEnumerable<Expression<Func<TE, Object>>> includeExpressions); 

    TE GetById(Expression<Func<TE, Boolean>> predicate); 
    void Create(TE entity); 
    void Update(TE entity); 
    void Delete(TE entity); 
} 

    public interface IEntityId<out TK> where TK : struct 
{ 
    TK Id { get; } 
    Int32 OwnerCode { get; } 
} 
+2

如果您要提供一个表达式,那么我在IEntityId接口中看不到该值 - 我错过了什么? – 2011-02-17 12:13:03