How to combine multiple linq queries into one result set?

I have a multi-select flag. Depending on which one is checked, I want to combine the results in one query. Example:

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.

Any idea how to combine them selectively?

+3
source share
4 answers

Assuming queries are of the same type, you can define queries outside of conditional statements.

Firstly, a helper method that creates an empty enumeration of the same type as the parameter:

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

Then the new 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

This runs just fine, because the requests are not actually executed until they are listed, as in a call ToList().

+8
source

var, , query1 query2

Enumerable.Empty<T> , .

0

I just tried this in a console application, as I was curious, and it just worked.

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

However, if I change the field names in anonymous types to be different, I get a compiler error, so it looks like the key should have the same names in your anonymous types. Or just the result in a specific type :)

0
source

Using Rx , you can do something like this:

public partial class _Default : System.Web.UI.Page
{
    IEnumerable<int> table1;
    IEnumerable<int> 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<int>())
            .Concat(
                Observable.If(() => CheckBox2.Checked,
                (from t in table2 select t).ToObservable(), Observable.Empty<int>())
            );

        query.Subscribe(i => Response.Write(i));
    }
}
0
source

Source: https://habr.com/ru/post/1752700/


All Articles