2009-01-31 8 views
1

Mes appologies d'avance pour la question longue. J'ai fait un effort pour que ma question soit aussi claire que possible en une fois. S'il vous plaît, supportez avec moi. o) toute aide sera grandement appréciée!Comment écrire une expression pour une propriété linq to sql?

J'ai les classes Direction et texte:

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 

Je veux afficher uniquement l'ID de la branche et sa description dans la langue appropriée. Je veux seulement une requête (pas d'aller-retour supplémentaire) qui récupère seulement deux champs (pas l'objet entier).

J'ai trouvé trois solutions

Via le modèle d'objet dans la requête

// 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; 

Via le modèle d'objet après la requête

// 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; 

En utilisant une expression

// 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; 

Voici le code pour les deux méthodes GetWebDescriptionAsString et 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; 
} 

Répondre

1

Sans vraiment répondre à la question, la plus propre approche serait de modifier la structure du texte en une forme plus normalisée comme:

Text 
    ID 

TextTranslation 
    ID 
    TextID 
    Lang 
    TextValue 

où chaque texte a un certain nombre de traductions, un pour chaque langue.

La requête deviendrait quelque chose comme:

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 
    }; 

Cette approche a d'autres avantages, par exemple l'ajout d'une nouvelle langue ne changera pas la structure du modèle.

+0

Oui, je sais. Mais les sql-experts nous ont promis que c'est la performance à suivre (pas sûr s'il a raison). De toute façon, changer la structure n'est plus une option. – Florian

+0

Je suis assez sûr qu'il n'a pas raison :) Une solution serait de mettre la condition directement dans la requête comme: WebDescription = lang == "NL"? b.Text.NL: lang == "FR"? b.Text.FR: ... Je ne l'ai pas testé mais je pense qu'il va produire un sql correct. – Aleris

0

Cela serait très facile à faire si vous utilisiez une procédure stockée. Êtes-vous opposé à l'utilisation de SP comme solution?

0

Si une procédure stockée fonctionne, alors je suis heureux de l'utiliser.

0

Sans comprendre votre problème tout

créer une procédure stockée comme ceci:

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] 


Ensuite, vous devez ajouter les sp à votre DBML et vous pouvez simplement appeler la sp vous avez besoin avec les paramètres appropriés:

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

    Dim str As String 
    str = query.MyText 

Le code ci-dessus ne doit pas être exact - Je ne comprends pas tous vos besoins, mais cela devrait vous aider à démarrer.

0

Merci pour votre réponse rapide.

J'ai fait une tentative rapide. L'UDF était déjà là, je ne savais juste pas comment l'utiliser.La performance a chuté de manière significative. La première solution est 3 fois plus rapide. À mon avis, cette approche nécessiterait des allers-retours supplémentaires à la base de données. Est-ce exact?

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

Ce n'est pas clair qui/ce que vous demandez ... essayez-vous de renvoyer tous les identifiants de branches, puis leurs descriptions, ou une seule branche et une seule description? –

Questions connexes