2012-01-28 68 views
5

我很確定我知道答案是否定的,但作爲最後一次嘗試,我想我會在這裏提出問題。是否可以手動修改IQueryable表達式

我使用EF代碼先查詢表以通常的方式

_context.Set<Foo>().Where(f => f.Bar == 999); 

它創建下面的表達式(我剛剛寫了這個,所以可能是錯誤的)。

{SELECT 
[Extent1].[Test] AS [Test], 
[Extent1].[Test2] AS [Test2], 
FROM [dbo].[Foo] AS [Extent1] 
WHERE 19 = [Extent1].[Bar]} 

現在,是否有可能手動修改此查詢,以更改表名稱,比如Foo10? (可能不是)

失敗的是,有沒有人知道一種方式,我可以「先後綁定」代碼中的表名?

您可能想知道「爲什麼骯髒的黑客?」像往常一樣,這是一個遺留問題,數據庫有一些設計問題,無法更改。

在此先感謝。

Ps。我知道我可以使用Database.SqlQuery但寧願不行。

+0

爲什麼在模型中沒有「Foo10」表? – BrokenGlass 2012-01-28 23:48:39

+0

因爲從技術上講,它的模型分佈在多個表中。您的數據所在的表格根據參數 – 2012-01-28 23:50:32

+0

@mjmcloug而有所不同,它是如何依賴的? – Krizz 2012-01-29 00:23:19

回答

0

這不是我會推薦的東西,但你可以ToString()查詢把SQL語句放到一個變量然後字符串替換表名。然後SQL執行該SQL?

臭和哈克但可能嗎?

+0

據我所知,只有在您願意拋棄Entity Framework的使用時纔有可能 - 這意味着無論如何您都可以手動編寫SQL。 – Bevan 2012-01-29 00:15:54

+0

我曾想過這樣做。它可能只會讀取這些數據,因此可能適合。想想看它有點狡猾:D – 2012-01-29 00:18:34

+0

@Bevan它不是完全浪費。這意味着我們可以用通常的方式建立表達式,並在最後一刻更改它,而不是爲每個我們想要的where子句創建一個新的sql查詢。 – 2012-01-29 00:20:36

1

假設您有合理數量的表格,我會將它們全部添加到模型中,並創建一個所有類將實現的通用接口,然後選擇適當的模型並使用Dynamic Linq進行查詢。

我不知道,如果這個工程,還沒有檢查它並沒有用「EF代碼優先」的工作,但是這是我想嘗試:

比方說,你的表(一個或多個)Foo有字段 - Bar,Pub,X和讓X是各自的表所依賴的?

然後,我將定義接口:

interface IFoo 
{ 
    int Bar { get; set; } 
    string Pub { get; set; } 
    int X { get; set; } 
} 

然後每桌都會有它的類模型:

[Table("Foo1")] 
class Foo1 : IFoo 
{ 
    public int Bar { get; set; } 
    public string Pub { get; set; } 
    public int X { get; set; } 
} 

[Table("Foo2")] 
class Foo2 : IFoo 
{ 
    public int Bar { get; set; } 
    public string Pub { get; set; } 
    public int X { get; set; } 
} 

然後,你可以像下面進行篩選:

IQueryable GetAdequateFoo(int X) 
{ 
    switch (X) // you could use reflection here to dynamically call the given Set<Foo#>() 
    { 
     case 1: 
     return _context.Set<Foo1>(); 
     case 2: 
     return _context.Set<Foo2>(); 
     default: 
     return null; 
    } 
} 

IFoo GetFooByBarAndX(int bar, int X) 
{ 
    IQueryable context = GetAdequateFoo(X); 
    return context.Where("it.Bar == @0", bar).Cast<IFoo>(); 
} 

它只是未經測試的建議,並從頭開始寫,如果我錯了,請不要倒票,並指出任何潛力小問題。

+0

哈,我不會放棄這個答案,它實際上是一個非常聰明的想法,將工廠方法應用於EF。我不會思考,因爲我也有映射類,所以它是很多類來設置它。雖然聰明的想法! – 2012-01-29 00:52:53

2

爲什麼不在模型上使用TPT繼承?

與@Krizz的答案類似,但您避免使用動態LINQ。

使用您的評論:

如果一個特定的參數有1個外觀在Foo1值如果2的外觀在foo2的等

所以,你可以這樣做:

var query = ctx 
    .Foos 
    .OfMyType(value) 
    .Where(f => f.Bar == 999) // f.Bar is on the base/abstract entity. 
    .ToList(); 

OfMyTypeIQueryable<T>自定義擴展方法:

public static IQueryable<T> OfMyType<T>(this IQueryable<T> source, string value) 
{ 
    switch (value) 
    { 
     case "1": 
     return source.OfType<Foo1>(); 
     case "2": 
     return source.OfType<Foo2>(); 
     // etc, etc 
    } 
} 

大多數(如果不是全部)屬性將位於抽象「Foo」實體上,並且爲每個表創建派生實體,每個表都有其自己的支持表。 「消費」代碼(例如查詢的代碼)不需要關心不同的表/ Foo,他們只是將「魔法值」傳遞給你的倉庫(希望你可以使用它),然後你可以靜靜地切換到你想要的桌子上。

會這樣嗎?

+0

再次,這看起來不錯。我將不得不放棄並回復你。但我唯一的問題是,它意味着產生很多我試圖避免的類。得愛傳統! – 2012-01-29 10:25:48

+1

+1很高興通過使用什麼框架提供簡化我的方法。 – Krizz 2012-01-29 11:53:47