2011-07-27 69 views
1

我正在將項目從標準數據庫查詢轉換爲使用EF和LINQ。我有了,我會用它來建立一個查詢,看起來像下面的某些記錄表:具有匿名類/屬性的LINQ

select * from client where city = ? 

我在原來的表,我會從表中可以拉動客戶端和城市構建查詢。

它也有可能是客戶機和城市以上可能是另一種表和/或字段完全。我如何與EF和LINQ做同樣的事情?這甚至是可能的,還是我必須建立一個單獨的類來處理所有這些邏輯?

var query = from c in context.clients 
      where c.city == ? 
      select c; 

編輯:這不是關於加入查詢。這是關於建立動態查詢。我不知道什麼時候運行該程序,無論我是在城市,地址還是甚至在「客戶端」表本身上查詢。它可能在另一張桌子上。我希望能夠動態構建查詢。

+2

我認爲我們需要更多的信息。我們來看看錶格定義。 –

+3

請說明。我無法遵循你想要的 –

回答

0

如果您想在實體框架中構建動態查詢,您可以經歷試圖動態構建表達式樹的麻煩。但是,實體框架爲您提供了一些其他選項。

首先,EntityObject有一些額外的對象服務方法,它已經讓你建立一個字符串,並將其傳遞直接到了一些謂詞,包括在哪裏:

c.Customers.Where("City = 'London'"); 

如果你需要建立更大的查詢,包括動態設置查詢源,考慮使用EntitySQL。例如與EntitySQL,您可以用簡單的字符串解析和生成類似下面的代碼:

string entitySQL = "SELECT VALUE c FROM Customers AS c WHERE c.Address.City = 'Seattle';"; 
ObjectQuery<Customer> query = context.CreateQuery<Customer>(entitySQL); 

可以在Entity Framework Query Samples看到這兩個選項中的作用。

+0

這是我在這裏尋找的線路,謝謝。有了這個,如果我在設計時不知道什麼是「客戶」,我將如何在運行時施加這個「客戶」? (因爲它可能是「客戶」,「訂單」等) – Zteck

+0

如果在運行時動態設置結果源列或投影列,則需要使用context.CreateQuery 。以下是EF Samples的示例:string entitySQL =「SELECT Min(p.UnitPrice)AS MinPrice,p.Category.CategoryName FROM Products AS p GROUP BY p.Category。CategoryName;「; ObjectQuery query = context.CreateQuery (entitySQL); –

0

如果你的表是由外鍵連接,你可以使用LINQ如下其它表訪問值。 (我被假設有一個「地址」表和客戶表有一個外鍵,它擴展您的例子。)

var query = from c in context.clients 
      where c.address.city == ? 
      select c; 

編輯:(試圖瞭解你原來的問題和後續評論。 ..)

認爲你問的是你是否可以這樣做?

string cityName = "Los Angeles"; // Could be a parameter, etc. 

var query = from c in context.clients 
      where c.city == cityName 
      select c; 

或者,把它從你的問題,也許這樣的事情更進了一步:

string cityName = (from c in context.cities 
        where c.id == 5 
        select c.name).FirstOrDefault(); 

var query = from c in context.clients 
      where c.city == cityName 
      select c; 

因爲它是一個IQueryable,您可以附加額外的條件,以及,對飛。

if (someCondition) 
{ 
    query = from q in query 
      where q.someField >= conditionValue 
      select q; 
} 

或其他。在實際需要結果之前,查詢表達式樹實際上不會被評估/執行。

+0

我一定不清楚。我有原始查詢它曾經是客戶和城市是由表提供的字符串值,我在飛行中構建查詢。我希望能夠在使用LINQ的EF中執行相同的操作,並且可以快速構建該LINQ查詢。這可能嗎? – Zteck

+0

是的,你不清楚。因此,從原始查詢中重新說明顯然是您的問題,您想知道您是否可以在運行時提供'?'? – GalacticCowboy

+0

如果這不是你要求的,也許你可以編輯你的問題提供更多的細節? – GalacticCowboy

0

您可以通過編寫提出GalacticCowboy查詢像

var query = from c in context.clients 
     join add in context.Addresses on c.AddressID equals add.AddressID 
     where addr.city == ? 
     select c; 

兩個查詢會產生內部連接在性能上沒有差異。唯一的區別是,如果客戶端的地址是可選的,那麼c.address.City將在沒有地址的客戶端上拋出異常,而這個查詢將返回一個空枚舉

0

如果你真的想在運行時建立你的查詢,那麼有一對基於linq的解決方案 - 您可以在運行時將代碼編譯爲臨時程序集,也可以使用其中一個MS示例中的DynamicLinq。

欲瞭解更多信息,請參閱的問題和答案:How to create LINQ Query from string?

0

我認爲有,你可以採取一些辦法。

首先,您可以查看Dynamic LINQ library(並參閱David Fowler對其的更新here)。使用這種方法,你可以寫你的LINQ查詢是這樣的:

var results = Context.Clients 
       .Where("city=='Los Angeles'") 
       .OrderBy("address"); 

所以你WhereOrderBy謂詞是得到引擎蓋下轉換爲字符串表達式。

其次,你可以使用像PredicateBuilder庫,如果你知道你的查詢是什麼,但不知道你是否會在一個或多個字段進行查詢,像這樣:

var predicate = PredicateBuilder.True<Clients>(); 
foreach(var criteria in searchCriteria) { 
    if (criteria.Key=="city"){ 
    predicate = predicate.And(c => c.city==criteria.Value); 
    } else if (criteria.Key=="address"){ 
    predicate = predicate.And(c => c.address==criteria.Value); 
    } 
} 
var results = Context.Clients.Where(predicate); 

第三,可能是最困難的是建立你自己的表達樹。這絕對需要最多的代碼(起初它有點深),但它非常非常強大。來自MSDN的這個example可以很好地解釋你可以做什麼(並且可能比我在這裏做得更簡潔一些)。

所以,基本上,你有幾個選項可供你選擇。動態LINQ庫似乎是最容易使用的,但我從來沒有使用它,所以我不能肯定地說它有多好,它有多可靠。如果有幫助的話,還有一個適用於Dynamic LINQ Library的NuGet軟件包。

祝你好運。希望這可以幫助!

+0

所有這些都適用於LINQ to SQL,但EF已經有了對象服務方法,可以在不需要謂詞構建器的情況下傳遞字符串。它實際上不會轉換爲表達式樹,而是轉換爲規範的查詢表達式。 –