2011-06-09 72 views
1

我想根據KeyValuePair列表查詢表。隨着模型的第一種方式,我可以做到以下幾點:實體框架4.0代碼優先動態查詢

var context = new DataContext(); 
var whereClause = new StringBuilder(); 
var objectParameters = new List<ObjectParameter>(); 

foreach(KeyValuePair<string, object> pair in queryParameters) 
{ 
    if (whereClause.Length > 0) 
     whereClause.Append(" AND "); 
    whereClause.Append(string.Format("it.[{0}] = @{0}", pair.Key)); 
    parameters.Add(new ObjectParameter(pair.Key, pair.Value)); 
} 

var result = context.Nodes.Where(whereClause.ToString(), parameters.ToArray()); 

現在我使用代碼優先方法和this Where method不再可用。幸運的是,我看到一篇文章的地方(我不記得了)這表明,我可以在DbContext轉換爲IObjectContextAdapter然後調用CreateQuery這樣的:

var result = ((IObjectContextAdapter)context) 
       .ObjectContext.CreateQuery<Node>(whereClause.ToString(), parameters.ToArray()); 

不幸的是,這將引發一個錯誤:

無法在當前範圍或上下文中解析'{ColumnName}'。確保所有引用的變量都在作用域中,所需的模式被加載,並且名稱空間被正確引用。

其中{ColumnName}是在whereClause中指定的列。

任何想法如何動態查詢DbSet給定的鍵/值對列表?所有的幫助將不勝感激。

+1

我們對此使用System.Linq.Dynamic。這是一個附加,但值得恕我直言。不是你問的問題,但它是一個可能的解決方案。 – 2011-06-09 18:11:46

+0

看起來像我在找什麼。我會檢查出來並報告回來......感謝提示! – 2011-06-09 18:47:29

+0

再次感謝克雷格!我真的很喜歡你的方法,它的工作原理。 – 2011-06-09 22:06:09

回答

2

我覺得你的第一個問題是,在第一個例子,你是在實體集,但你是第二個例子中使用Where使用CreateQuery,所以您必須通過完整的ESQL查詢,而不僅僅是where子句!嘗試是這樣的:

... 
.CreateQuery<Node>("SELECT VALUE it FROM ContextName.Nodes AS it WHERE " + yourWhere) 

最成問題的是全部的實體設置在FROM部分名稱。我認爲它被定義爲在上下文中公開的上下文類的名稱和DbSet的名稱。另一種方法是創建ObjectSet

... 
.ObjectContext.CreateObjectSet<Node>().Where(yourWhere) 
+0

+1因爲一般是正確的,但是如果「where」涉及用戶數據,則使用params或sanitize。 – 2011-06-09 19:56:33

+0

@克雷格:我同意。我只是讓這個例子太蹩腳。 Where子句不應該使用字符串連接構建。 – 2011-06-09 19:58:48

+0

當我嘗試第二個建議時,出現錯誤:** DbContext不包含「CreateObjectSet」的定義並且沒有擴展方法.... ** – 2011-06-09 21:16:15