关于c#:如何合并两个LINQ查询,但第二个查询需要具有更多字段

How to union two LINQ queries but the second query need have more fields

我需要在两个LINQ查询之间建立联合,但是第二个查询需要比第一个查询更多的字段。我该怎么办?

示例:

1
2
3
4
5
6
7
8
public static void Dummy()
{
    var query1 = this.Db.Table1.Select(s => new MyObject() { A = s.Field1, B = s.Field2 });

    var query2 = this.Db.Table2.Select(s => new MyObject() { A = s.Field1, B = s.Field2, C = s.Field3 });

    var result = query1.Union(query2);
}

当我调用result.ToList()时,发生以下错误:

The type 'MyObject' appears in two structurally incompatible
initializations within a single LINQ to Entities query. A type can be
initialized in two places in the same query, but only if the same
properties are set in both places and those properties are set in the
same order.

如何解决此问题?

好。:我无法将Field3放在query1中(我无权访问查询一个,因为这无法更改)


您不必在第一个查询中放入Field3,但是Union需要相同数量的列和相同的顺序。为第三列/字段C指定一个虚拟值,例如:

1
2
var query1 = this.Db.Table1.Select(s => new MyObject()
                        { A = s.Field1, B = s.Field2 , C=""});

分配C的默认值是Field3,对于引用类型可以为null,对于数字等可以为0

如果您无权访问它,请修改query1,然后使用query1创建一个新查询,例如:

1
2
var newQuery = query1.Select(s=> new MyObject()
                            { A = A, B = B , C=""});

,然后在Union

中使用它

1
var result = newQuery.Union(query2);


不能那样做。您只能合并具有相同结构的2个集。如果您不介意修改query1,请执行以下操作:

1
2
var query1 = this.Db.Table1.Select(s => new MyObject()
                                        { A = s.Field1, B = s.Field2, C = null });

这将允许它们正确地合并,因为它们具有相同的结构。


您可以这样做,例如:

创建一个从MyObject

出发的对象

1
2
class MyObjectUnion : MyObject{
}

因此,方法如下:

1
2
3
4
5
6
7
8
9
10
public static void Dummy()
{
    var query1 = this.Db.Table1.Select(s => new MyObject() { A = s.Field1, B = s.Field2 });

    var query1modified = this.Db.Table2.Select(s => new MyObjectUnion() { A = s.Field1, B = s.Field2, C = null });

    var query2 = this.Db.Table2.Select(s => new MyObjectUnion() { A = s.Field1, B = s.Field2, C = s.Field3 });

    var result = query1modified.Union(query2);
}

有效


因为query1中的记录永远不会具有属性" C",而query2中的所有记录都将具有属性" C",所以query1中的记录不太可能等同于query2中的记录。在Concat上使用Union的唯一原因是删除重复项,并且由于没有重复项,因此您可能应该使用Concat而不是Union。

1
2
3
4
5
6
7
8
public static void Dummy()
{
    var query1 = this.Db.Table1.Select(s => new MyObject() { A = s.Field1, B = s.Field2 });

    var query2 = this.Db.Table2.Select(s => new MyObject() { A = s.Field1, B = s.Field2, C = s.Field3 });

    var result = query1.ToList().Concat(query2);
}

有些例外,例如您有一个针对MyObject的自定义IEqualityComparer,而忽略了" C"属性,或者" C"属性的默认值可能存在于table2的记录中,并且您想要删除重复项,或者如果query1或query2中可能存在重复项,并且您希望将其删除,则仍然可以使用Concat,但是需要在Concat之前使用Distinct。

编辑以强制在通过.ToList()串联之前实现query1。

使用LinqPad进行了双重检查,并且使用具有同时具有Category和Cities表的数据源的完全不同的模式的以下可执行文件没有问题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void Main()
{
    var query1 = Categories.Select(s => new MyObject { A = s.id, B = s.name });

    var query2 = Cities.Select(s =>  new MyObject { A = s.id, B = s.city_name, C = s.location });

    var result = query1.ToList().Concat(query2);
    result.Dump();
}
public class MyObject
{
    public int A {get;set;}
    public string B {get;set;}
    public object C {get;set;}
}