C# 如何合并两个LINQ查询,但第二个查询需要更多字段
我需要在两个LINQ查询之间进行联合,但是第二个查询需要比第一个查询有更多的字段。我怎么做 例如:C# 如何合并两个LINQ查询,但第二个查询需要更多字段,c#,linq,entity-framework,C#,Linq,Entity Framework,我需要在两个LINQ查询之间进行联合,但是第二个查询需要比第一个查询有更多的字段。我怎么做 例如: 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.Field
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()时,发生以下错误:
“MyObject”类型出现在两个结构不兼容的类型中
在单个LINQ到实体查询中进行初始化。类型可以是
在同一查询中的两个位置初始化,但仅当
属性在两个位置都设置,并且这些属性在
同样的顺序
我如何解决这个问题
Obs.:我无法将
字段3
放入查询1
(我无法访问查询1,因为我无法更改它)您不必在第一次查询中放入字段3
,但Union
要求相同的列数和顺序。为第三列/字段C
指定虚拟值,如:
var query1 = this.Db.Table1.Select(s => new MyObject()
{ A = s.Field1, B = s.Field2 , C= ""});
var newQuery = query1.Select(s=> new MyObject()
{ A = A, B = B , C= ""});
分配C
任何Field3
的默认值,对于参考类型可以是null
,对于数字等可以是0
如果您没有访问权限,请修改query1
,然后使用query1
创建一个新查询,如:
var query1 = this.Db.Table1.Select(s => new MyObject()
{ A = s.Field1, B = s.Field2 , C= ""});
var newQuery = query1.Select(s=> new MyObject()
{ A = A, B = B , C= ""});
然后在Union
var result = newQuery.Union(query2);
事实上,你不能。只能合并两个具有相同结构的集合。但是,如果您不介意修改
查询1
,请执行以下操作:
var query1 = this.Db.Table1.Select(s => new MyObject()
{ A = s.Field1, B = s.Field2, C = null });
这将允许它们正确地合并,因为它们具有相同的结构。因为query1中的记录永远不会有属性“C”,而query2中的所有记录都会有属性“C”,所以query1中的记录不太可能等同于query2中的记录。在Concat上使用Union的唯一原因是删除重复项,因为您不能有任何重复项,所以您应该使用Concat而不是Union
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);
}
也有例外,例如,如果您有一个自定义IEqualityComparer for MyObject,它忽略了“C”属性,或者“C”属性的默认值可能存在于表2的记录中,并且您希望删除重复项,或者如果query1或query2中可能存在重复项,并且您希望删除它们,那么您仍然可以使用Concat,但是你需要在Concat之前使用Distinct
编辑以强制query1在通过.ToList()连接之前实现
使用LinqPad进行了双重检查,以下可执行文件没有问题,使用的数据源的类别和城市表都是完全不同的模式:
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;}
}
你可以这样做:
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);
}
创建与MyObject不同的对象
class MyObjectUnion : MyObject{
}
因此,方法如下:
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);
}
它可以工作错误消息是不言自明的!如果您已经在SQL Server等中使用了
Union
,那么很容易理解它的意思。我无法更改查询1,因为我没有访问该查询的权限。@RenatoLeite,您可以在query1
上创建一个新查询,我添加了一些新代码,尝试一下。我尝试了,但没有解决问题,错误持续存在:(@RenatoLeite取决于返回的数据的大小,以及是否需要读取所有记录。如果不需要读取所有记录(或多次读取),请将.ToList()更改为.AsEnumerable()