2012-02-13 26 views
2

我有一個多租戶應用程序,並且所有數據都在同一個數據庫中。我們通過objectToTenant表分割每個租戶的數據。插入Func <T, int>值到linq-2-sql查詢

在一般存儲庫類我想要實現其過濾的對象的方法只是通過指定該對象的屬性是tenantToObjectRelationId和什麼類型是對象(必要的,因爲不同類型的存儲在關係表)

我要讓看起來應該像這樣的電話:

// Specialized Repository class 
var allItemsForTenant = 
    this.AllForTenant(item => item.RelationId, 123); 

,所以我實現了這個方法:

// Generic Repository class 
public virtual IQueryable<T> AllForTenant(
    Func<T, int> getObjectToTenantRelationId, string objectType) 
{ 
    var result = 
     from item in this.context.GetTable<T>() 
     join tenantObject in (
      from tenantRelationRecord in objectTenantRelationRepo.All() 
      where tenantRelationRecord.TenantId == Global.TenantId 
      where tenantRelationRecord.ObjectTypeId == type.TypeId 
      select tenantObjectRecord) 
      on getObjectToTenantRelationId(item) equals tenantObject.ObjectId 
     select item; 

    return result; 
} 

但此刻我得到了NotSupportedException

毛皮死System.Object的DynamicInvoke(System.Object的[]) - 了Methode gibt ES keineunterstützteÜbersetzung在SQL。

這是由Func<T, int>方法引起的,不能被轉換成sql。

我該如何更改Func<T, int>以便它可以被翻譯或做別人的解決方案?

+0

而不是在'IQueryable'中傳遞'Func '傳入所有可能的項目並使用它們加入。 – Steven 2012-02-13 11:08:39

+0

對於Entity Framework能夠翻譯它,你必須傳遞一個'Expression >'。 – 2012-02-13 11:12:31

回答

0

一個簡單的解決辦法是通過Expression<Func<T,int>>,而不是僅僅Func<T,int>。傳遞一個表達式將允許樹訪問者「進入」你的表達而不是反彈它的名字。

好的是,如果你通過lambda表達式,編譯器會自動創建Expression<Func<T,int>>,因此你唯一需要改變的就是你的AllForTenant方法的簽名。

+0

如果我將簽名更改爲'Expression >',我得到錯誤''getObjectToTenantRelationId''是一個'變量',但用法類似' – Viper 2012-02-13 11:28:17

+0

只有當LINQ to SQL可以將其轉換爲SQL時,才能使用「Expression」 。 – Steven 2012-02-13 11:43:26

+0

@Viper:雖然我不知道如何使用查詢式語法來應用'表達式>,但是如果您查看擴展方法的語法,那麼'.Join()'接受表達式。我已經多次使用它來進行過濾,並且情況也是如此 - 您必須切換到'.Where()'over'where'。 – 2012-02-13 12:18:22

0

而不是通過Func<T, int>傳遞IQueryable<Tuple<T, int>>或類似的東西。這LINQ to SQL的方式知道如何將其翻譯爲SQL:

// Generic Repository class 
public virtual IQueryable<T> AllForTenant(
    IQueryable<Tuple<T, int>> objectToTenentRelationIds, string objectType) 
{ 
    var tenantObjects = 
     from tenantRelationRecord in objectTenantRelationRepo.All() 
     where tenantRelationRecord.TenantId == Global.TenantId 
     where tenantRelationRecord.ObjectTypeId == type.TypeId 
     select tenantObjectRecord; 

    var result = 
     from item in this.context.GetTable<T>() 
     join objectToTenentRelationId in objectToTenentRelationIds 
      on objectToTenentRelationId.Item1 equals item 
     join tenantObject in tenantObjects 
      on objectToTenentRelationIds.Item2 equals tenantObject.ObjectId 
     select item; 

    return result; 
} 
+0

如果我按照你的建議,那麼我需要在調用通用基礎知識庫的方法之前選擇所有對象並將它們作爲參數傳遞。這是我嘗試避免執行的事情。 – Viper 2012-02-13 11:31:55

+0

不必從數據庫中獲取所有內容。別忘了'IQueryable'只是查詢的定義,而不是數據本身。 LINQ to SQL將把它轉換爲高效的SQL查詢。 – Steven 2012-02-13 11:39:51

+0

對不起,也許我沒有表達清楚。我的意思是,當我想執行你的查詢時,我需要在專門的存儲庫中做一個額外的linq-2-sql查詢,以便能夠將'IQueryable'傳遞到BaseRepository方法中。如果我需要這樣做,那麼我可以直接在專門的存儲庫中加入到objectTenantRelation中。 – Viper 2012-02-13 11:48:20

相關問題