C# Linq左连接向左对象添加数据

C# Linq左连接向左对象添加数据,c#,linq,linq-extensions,C#,Linq,Linq Extensions,我有3个实体: class Foo { public Guid? BarId { get; set; } //Has optional bar [NotMapped] public boolean? HasXyzzy { get; set; } } class Bar { ... } class Xyzzy { public Guid BarId { get; set; } //Always has Bar } 我想从数据库中检索一些Foo,并填充它们的hasxyzy

我有3个实体:

class Foo {
  public Guid? BarId { get; set; } //Has optional bar

  [NotMapped]
  public boolean? HasXyzzy { get; set; }
}

class Bar {
  ...
}

class Xyzzy {
  public Guid BarId { get; set; } //Always has Bar
}
我想从数据库中检索一些
Foo
,并填充它们的
hasxyzy
属性。我正在使用LINQ到实体扩展方法

我在想这样的事情:

var xyzzys = xyzzyRepository.GetAll(); //IQueryable

var foos = fooRepository.GetAll()
    .Where() //Some condition
    .SelectMany(
        foo => xyzzys.Where(xyzzy => xyzzy.BarId == foo.BarId).DefaultIfEmpty(),
        (foo, xyzzy) => new Foo {
            BarId = foo.BarId,
            HasXyzzy = xyzzy != null
        });
但这是相当乏味的,因为我的Foo类有很多属性

正确的方法是什么?

您的代码:

 (foo, xyzzy) => new Foo {
                BarId = foo.BarId,
                HasXyzzy = xyzzy != null
            });
您已经有一个Foo作为参数,因此可以更改您在其中传递的委托:

 (foo, xyzzy) =>
 { 
     foo.HasXyzzy = xyzzy;
     return foo;
 });
如果我错了,请纠正我,fooRepository带来了
列表
,在left join之后,您只需要使用join的附加数据来完成它们

更新: 实际上我错了,因为我们这里有IQueryable,它的表达式是param而不是delegate,并且不能将带有语句体的lambda转换为表达式树

现在,另一个想法不是最好的,因为它将使用额外的迭代,但仍然-是转换为IEnumerable并执行相同的技巧

    (foo, xyzzy) => new {
                   foo, xyzzy                   
                }).AsEnumerable()
.Select(x=> 
{ 
     foo.HasXyzzy = xyzzy;
     return foo;
});

我不认为LINQ对SQL/EF(6)/EF Core 2/EF Core 3起作用。@NetMage yep,更新为AsEnumerable实现,谢谢您的评论。如果我没有弄错的话,AsEnumerable()实际上会触发对数据库的调用,而不是仅仅转换为查询,对吗?有没有办法避免这种情况?是的,AsEnumerable()之前的所有内容都将在db端执行,之后的所有内容都在代码端执行。不幸的是,我似乎没有找到更优雅的解决方案。由于它假定可以转换为sql,因此在当前版本的EF中似乎不可能。我非常确定,当您从数据库检索时,您应该调用
new Foo
。这取决于提供程序以及您是希望在内存中执行此操作还是转换为查询。看看这个