2009-01-31 28 views
1

我對這個冗長的問題提出了一些先例。我盡力使問題一目瞭然。請多多包涵。 ; o)任何幫助將不勝感激!如何將linq表達式寫入sql屬性?

我有類科和文本:

class Branch 
int ID 
Text WebDescription 
and a bunch of other properties 

class Text 
int ID 
string UK 
string NL 
string FR 
string IT 
and a bunch of other properties as well 

我想只顯示該分支的ID及其相應的語言描述。我只想要一個查詢(沒有額外的往返行程),它只檢索兩個字段(而不是整個對象)。

我發現了三個解決方案

通過查詢

// good: no round trips 
// good: clean sql 
// bad: impossible to use the currentUserLanguage parameter 
var lang = "NL"; 
var dbProject = new ProjectDataContext(); 
var query = from b in dbProject.GetTable<Branch>() 
      select new 
       { 
       b.ID, 
       WebDescription = b.WebDescriptionObject.NL // <-- problem 
       }; 
var text = query.First().WebDescription; 

對象模型通過對象模型查詢

// good: no round trips (eager loading of text object) 
// good: possible to use the currentUserLanguage parameter 
// bad: loads the *whole* branch and text object, not just two fields 
var lang= "NL"; 
var dbProject = new ProjectDataContext(); 
var query = from b in dbProject.GetTable<Branch>() 
      select new 
       { 
       b.ID, 
       WebDescription = b.GetWebDescriptionAsString(lang) 
       }; 
var text = query.First().WebDescription; 

之後,利用表達

// good: I have the feeling I am on the right track 
// bad: This doesn't work :o(throws an exception 
var lang= "NL"; 
var dbProject = new ProjectDataContext(); 
var query = from b in dbProject.GetTable<Branch>() 
      select new 
       { 
       b.ID, 
       WebDescription = b.GetWebDescriptionAsExpression(lang) 
       }; 
var text = query.First().WebDescription; 

這裏是GetWebDescriptionAsString和GetWebDescriptionAsExpression兩個方法的代碼。

public string GetWebDescriptionAsString(string lang) 
{ 
    if (lang== "NL") return WebDescriptionObject.NL; 
    if (lang== "FR") return WebDescriptionObject.FR; 
    if (lang== "IT") return WebDescriptionObject.IT; 
    return WebDescriptionObject.UK; 
} 

public Expression<Func<Branch, string>> GetWebDescriptionAsExpression(string lang) 
{ 
    if (lang== "NL") return b => b.WebDescriptionObject.NL; 
    if (lang== "FR") return b => b.WebDescriptionObject.FR; 
    if (lang== "IT") return b => b.WebDescriptionObject.IT; 
    return b => b.WebDescriptionObject.UK; 
} 

回答

1

沒有真正回答這個問題,最乾淨的方法是更改​​文本結構成爲一個更規範化的形式,如:

Text 
    ID 

TextTranslation 
    ID 
    TextID 
    Lang 
    TextValue 

其中每個文本有一些翻譯,每種語言一個。

查詢將成爲類似:

var q = 
    from branch in dbProject.Branches 
    join text in dbProject.Texts on branch.TextID = text.ID 
    join translation in dbProject.TextTranslations on text.ID = translation.TextID 
    where translation.Lang == lang 
    select new 
    { 
     branch.ID, 
     WebDescription = translation.TextValue 
    }; 

這種方法具有其他優點,例如增加一個新的語言不會改變模型結構。

+0

是的,我知道。但是sql-experts向我們承諾這是一種表現明智的方式(不確定他是否正確)。無論如何改變結構不再是選擇。 – Florian 2009-01-31 13:16:45

+0

我很肯定他是不對的:) 一個解決方案是將條件直接放在查詢中,例如: WebDescription = lang ==「NL」? b.Text.NL:lang ==「FR」? b.Text.FR:...沒有測試它,但我認爲它會產生一個合適的SQL。 – Aleris 2009-01-31 13:34:03

0

如果您使用存儲過程,這將會非常容易。你是否反對使用SP作爲解決方案?

0

如果存儲過程有效,那麼我很樂意使用它。

0

不理解你的整個問題

創建一個存儲過程是這樣的:

CREATE PROCEDURE spGetTheTextINeed @Language char(2), @BranchID int 
AS 
    /* I don't know how your database is structured so you need to write this */ 
    SELECT MyText from MyTable WHERE [email protected] and [email protected] 


然後,你需要給SP添加到您的DBML,然後你可以直接撥打SP你需要用相應的參數:

var query = myDataContext.spGetTheTextINeed("NL",[your branch number]) 

    Dim str As String 
    str = query.MyText 

上面的代碼不是確切的 - 我不明白你的全部要求,但這應該讓你開始。

0

謝謝您的及時回覆。

我做了一個快速嘗試。 UDF已經在那裏,我只是不知道如何使用它。表現大幅下降。第一種解決方案速度提高3倍。根據我的理解,這種方法需要額外往返數據庫。那是對的嗎?

var query = from b in dbProject.GetTable<Branch>() 
      select new 
       { 
       b.ID, 
       WebDescription = db.fGetText(b.WebDescriptionID, (currentUserLanguage)) 
       }; 
相關問題