2011-05-20 119 views
2

我有以下代碼:實體框架,LINQ和泛型

public interface IKeyed<TKey> 
{ 
    TKey Id { get; } 
} 

// This is the entity framework generated model. I have added the 
// IKeyed<Guid> interface 
public partial class Person : IKeyed<Guid> 
{ 
    public Guid Id { get; set; } 
} 

public class Repository<TKey, TEntity> : IKeyedRepository<TKey, TEntity> 
       where TEntity : class, IKeyed<TKey> 
{ 
    private readonly IObjectSet<TEntity> _objectSet; 

    public Repository(IOjectSet<TEntity> objectSet) 
    { 
     _objectSet = objectSet; 
    } 

    public TEntity FindBy(TKey id) 
    { 
     return _objectSet.FirstOrDefault(x => x.Id.Equals(id)); 
    } 
} 

[更新] 這是我如何打電話這一點:

Db2Entities context = new Db2Entities(_connectionString); // This is the EF context 
IObjectSet<Person> objectSet = context.CreateObjectSet<Person>(); 

IKeyedRepository<Guid, Person> repo = new Repository<Guid, Person>(objectSet); 

Guid id = Guid.NewGuid(); 
Person person = repo.FindBy(id); // This throws the exception. 

上面的代碼編譯。執行'FindBy'方法時,出現以下錯誤:

無法創建類型爲'閉包類型'的常量值。在此上下文中僅支持基本類型(例如Int32,String和Guid)。

由於我的'Id'的類型是一個Guid(支持的基本類型之一),似乎我應該能夠按摩這個工作。

任何人都知道這是可能的嗎?

感謝,

鮑勃

+1

如果我必須通過我的冒險來判斷寫入linq提供者的東西,我假設EF的提供者分析首先給出的表達式或默認的類型。而id的類型是不是typeof(Guid)的TKey。 – TDaver 2011-05-20 20:48:51

+0

我相信TDaver是對的。如果你有一個非泛型參數'Guid'而不是泛型'TKey'參數,那麼代碼實際上可以工作。 – Slauma 2011-05-21 12:24:24

回答

3

它不以這種方式工作。您不能撥打Equals,因爲EF不知道如何將其轉換爲SQL。當您將表達式傳遞給FirstOrDefault時,它必須始終只有可以轉換爲SQL的代碼。可能通過手動構建表達式樹來解決您的問題,但我可以參考Stack Overflow中已經討論過的其他解決方案。

ObjectContext提供了一種名爲GetObjectByKey的方法,這正是您所要做的。問題是它需要EntityKey作爲參數。這裏有兩個答案,顯示瞭如何使用此方法,以及如何獲得EntityKey

在你的情況下,代碼會那麼複雜,因爲你知道的名字關鍵屬性,所以你通常只需要這樣的事情:

public virtual TEntity FindBy(TKey id) 
{ 
    // Build entity key 
    var entityKey = new EntityKey(_entitySetName, "Id", key); 
    // Query first current state manager and if entity is not found query database!!! 
    return (TEntity)Context.GetObjectByKey(entityKey); 
} 

這裏的問題是,你不能得到entitySetName from IObjectSet因此您必須將其傳遞給存儲庫構造函數,否則您必須通過ObjectSet

以防萬一,你會希望在未來,而不是ObjectContext的API將大大簡化使用的DbContext API(EFv4.1),因爲DbSet提供Find方法:

+0

我相信'Equals'不是問題。通常它允許在LTE中轉換爲SQL。我認爲問題屬於引起異常的LTE查詢(通用TKey參數)中的「引用非標量變量」的類別(http://msdn.microsoft.com/zh-cn/library/bb896317。 aspx) – Slauma 2011-05-21 12:29:38

+0

我能夠使用@Ladislav建議來實現。如果您有興趣查看最終結果,請訪問https://github.com/rcravens/GenericRepository – rcravens 2011-05-21 13:47:45