2009-09-01 5 views
2

J'ai une paire de Linq à des requêtes SQL qui contiennent la même clause WHERE complexe, plus précisément:Options pour le partage de code dans Linq2SQL expressions

where ((range.MinimumFrequency <= minFreq && minFreq <= range.MaximumFrequency) 
|| (range.MinimumFrequency <= maxFreq && maxFreq <= range.MaximumFrequency) 
|| (range.MinimumFrequency <= minFreq && maxFreq <= range.MaximumFrequency) 
|| (range.MinimumFrequency >= minFreq && maxFreq >= range.MaximumFrequency)) 

Et plutôt que de copier et coller ce morceau de code dans tous les sens , Je voulais refactoriser dans quelque chose d'autre qui peut être partagé. Je sais que je ne peux pas le faire avec une méthode normale car il ne peut pas être traduit en SQL, mais je ne peux pas non plus obtenir les

Expression < Func<...>>

choses described here travailler non plus.

Si je simplifie la clause where dans le but de ma santé mentale ici, je veux tourner

where (range.MinumumFrequency < minFreq) 

dans une expression, alors j'ai essayé:

public static Expression<Func<FreqRange, bool>> Overlaps(decimal minMHz, decimal maxMHz) 
{ 
    return (range => range.MinimumFrequency <= minMHz); 
} 

Cela semble compiler, mais Je ne peux pas sembler obtenir l'instruction where au travail, j'ai essayé ce qui suit:

where FreqRange.Overlaps(minMHz, maxMHz) 

mais cela me donne une erreur de compilation:

Cannot implicitly convert type 'System.Linq.Expressions.Expression>' to 'bool'

Toutes les idées? Aussi, en supposant que nous obtenons ce fonctionnement, puis-je simplement étendre l'expression lambda dans l'expression < Func < >> pour inclure les autres conditions?

Répondre

2

Si vous utilisez la syntaxe LINQ langage builting, vous déclarant implicitement une expression de lamba - et que expression lamba est un Expression<Func <>> - donc vous n'avez pas besoin de la clause where à retour l'expression, vous besoin de être l'expression.

par exemple.

var q = from row in myTable 
     where row.a < aMax 
     select row.b; 

// which translates to 

var q = myTable.Where(row => row.a < aMax).Select(row => row.b); 

Maintenant, vous devez "cache" row => row.a < aMax - pas seulement la valeur de row.a < aMax, si vous voulez. Donc, si vous deviez écrire quelque chose comme ça ...

Expression<Func<?,bool>> cachedExpression = row => row.a < aMax; 

var q = from row in myTable 
     where cachedExpression 
     select row.b; 

Eh bien, vous dites « où, donné une ligne, il est vrai que (donné une ligne, il est vrai que rangée.Un est moins que aMax) ". Cela n'a aucun sens et ne sera pas compilé si cachedExpression est de type Expression<Func<?,bool>> et myTable est une table fournie par LinqToSql. Il se traduirait par quelque chose comme ceci:

Expression<Func<?,bool>> cachedExpression = row => row.a < aMax; 

//nonsense .Where: 
var q = myTable.Where(row => cachedExpression).Select(row => row.b); 
//effectively says this: 
var q = myTable.Where(row => (row0 => row0.a < aMax)).Select(row => row.b); 

Maintenant, c'est juridique dans le sens où il est possible pour un fournisseur de requête LINQ pour mettre en œuvre une whereClause avec une valeur non booléenne, mais il est un chose très étrange à faire; certainement pas de fournisseurs linq standard (tels que Linq to Sql) font une telle chose.

Alors que faut-il faire?Quelque chose comme:

//not .Where(row=>cachedExpression)! 
var q = myTable.Where(cachedExpression).Select(row => row.b); 

//or, alternatively: 
var q = from filteredRow in myTable.Where(cachedExpression) 
     select filteredRow.b; 
1

Vous pouvez également créer une méthode qui prend et envoie IQueryable. J'ai utilisé ces vues similaires, mais purement dans le code.

public class WithProps 
{ 
    public string Prop1 { get; set; } 
    public string Prop2 { get; set; } 
    public override string ToString() 
    { 
     return string.Format("{0}-{1}", Prop1, Prop2); 
    } 
} 

public static class Tools 
{ 
    public static IQueryable<WithProps> MyFilter(this IQueryable<WithProps> props) 
    { 
     return props.Where(p => p.Prop1 == "hi"); 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     var propList = new List<WithProps>() 
     { 
      new WithProps(){ Prop1="hi", Prop2="there"}, 
      new WithProps(){ Prop1="hi", Prop2="bye"}, 
      new WithProps(){ Prop1="hello", Prop2="world"}, 
      new WithProps(){ Prop1="bye", Prop2="friend"} 
     }; 

     var filtered = propList.AsQueryable().MyFilter(); 

     Console.WriteLine("propList ==="); 
     foreach (var item in propList) 
      Console.WriteLine(item.ToString()); 
     Console.WriteLine("filtered ==="); 
     foreach (var item in filtered) 
      Console.WriteLine(item.ToString()); 
    } 
} 

... résultats ...

propList === 
hi-there 
hi-bye 
hello-world 
bye-friend 
filtered === 
hi-there 
hi-bye 
Questions connexes