Comment combiner plusieurs requêtes linq dans un seul jeu de résultats?

J’ai une case à cocher multiple. En fonction de celui qui est coché, je souhaite combiner les résultats en une seule requête. Un peu comme:

if (Checkbox1.Checked) { var query1 = from t in table1 ... } if (Checkbox2.Checked) { var query2 = from t in table2 ... } DataGridView1.DataSource = query1.Union(query2); // obviously doesnt // work since query1 and query2 are not defined in this scope. 

Avez-vous une idée de la manière de les combiner sélectivement

En supposant que les requêtes soient du même type, vous pouvez définir les requêtes en dehors des instructions conditionnelles.

Tout d’abord, une méthode d’assistance qui crée un énumérable vide du même type que le paramètre:

 static IEnumerable CreateEmptyEnumerable(IEnumerable templateQuery) { return Enumerable.Empty(); } 

Ensuite, le nouveau code:

 var query1 = from t in table1 ... var query2 = from t in table2 ... var finalQuery = CreateEmptyEnumerable(query1); if (Checkbox1.Checked) { finalQuery = query1; } if (Checkbox2.Checked) { finalQuery = finalQuery.Union(query2); } DataGridView1.DataSource = finalQuery.ToList(); // to avoid re-enumeration 

Cela fonctionne parfaitement car les requêtes ne sont pas exécutées tant qu’elles ne sont pas énumérées, comme dans l’appel à ToList() .

Si vous ne voulez pas utiliser var mais un type connu, vous pouvez initialiser query1 et query2 via

Enumerable.Empty si la case à cocher n’est pas cochée.

Je viens d’essayer cela dans une application console, car j’étais curieux, et cela a juste fonctionné …

 class Program { private class Data1 { public int Code1 { get; set; } public ssortingng Value1 { get; set; } } private class Data2 { public int Code2 { get; set; } public ssortingng Value2 { get; set; } } static void Main(ssortingng[] args) { var data1 = new[] { new Data1 { Code1 = 1, Value1 = "one" }, new Data1 { Code1 = 2, Value1 = "two" }, new Data1 { Code1 = 3, Value1 = "three" } }; var data2 = new[] { new Data2 { Code2 = 101, Value2 = "aaa" }, new Data2 { Code2 = 102, Value2 = "bbb" }, new Data2 { Code2 = 103, Value2 = "ccc" } }; var query1 = from d1 in data1 select new { code = d1.Code1, text = d1.Value1 }; var query2 = from d2 in data2 select new { code = d2.Code2, text = d2.Value2 }; var datasource = query1.Union(query2); foreach (var d in datasource) { Console.WriteLine(d); } } } 

Cependant, si je modifie les noms de champs dans les types anonymes pour qu’ils soient différents, une erreur de compilation se produit, de sorte que la clé semble avoir les mêmes noms dans vos types anonymes. Ou juste avoir le résultat dans un type défini 🙂

En utilisant Rx, vous pouvez faire quelque chose comme ceci:

 public partial class _Default : System.Web.UI.Page { IEnumerable table1; IEnumerable table2; protected void Page_Load(object sender, EventArgs e) { table1 = Enumerable.Range(0, 10); table2 = Enumerable.Range(10, 10); } protected void Button1_Click(object sender, EventArgs e) { var query = Observable.If(() => CheckBox1.Checked, (from t in table1 select t).ToObservable(), Observable.Empty()) .Concat( Observable.If(() => CheckBox2.Checked, (from t in table2 select t).ToObservable(), Observable.Empty()) ); query.Subscribe(i => Response.Write(i)); } }