¿Cómo combino varias consultas de linq en un conjunto de resultados?

Tengo una casilla de selección múltiple. Dependiendo de cuál esté marcado, quiero combinar los resultados en una sola consulta. Algo así como:

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. 

¿Alguna idea de cómo combinar estos selectivamente?

Suponiendo que las consultas sean del mismo tipo, podría definir las consultas fuera de las sentencias condicionales.

Primero, un método auxiliar que crea un enumerable vacío del mismo tipo que el parámetro:

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

Entonces, el nuevo código:

 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 

Esto funciona bien porque las consultas no se ejecutan hasta que se enumeran, como en la llamada a ToList() .

Si no usaría var sino un tipo conocido, entonces podría inicializar query1 y query2 a través de

Enumerable.Empty en caso de que la checkbox no esté marcada.

Acabo de intentar esto en una aplicación de consola, ya que tenía curiosidad, y simplemente funcionó …

 class Program { private class Data1 { public int Code1 { get; set; } public string Value1 { get; set; } } private class Data2 { public int Code2 { get; set; } public string Value2 { get; set; } } static void Main(string[] 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); } } } 

Sin embargo, si cambio los nombres de campo en los tipos anónimos para que sean diferentes, obtengo un error del comstackdor, así que parece que la clave es tener los nombres iguales en sus tipos anónimos. O simplemente tener el resultado en un tipo definido 🙂

Usando Rx puedes hacer algo como esto:

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