使用LINQ选择和组合对象的正确方法是什么?

Jos*_*ank 5 .net linq

这是我经常遇到的情况:我有父对象和子对象,而Child对象有一个Parent属性.我想运行一个获取子对象的查询,并将每个对象连接到正确的父对象:

Dim db = New DataContextEx()

get the children, along with the corresponding parent
Dim Children = From x In db.ChildTable
                Join y In db.ParentTable
                On x.ParentId Equals y.Id
                Execute x.Parent = y       <-- pseudocode
                Select x   
Run Code Online (Sandbox Code Playgroud)

伪代码显示了我想要完成的任务:返回子对象x,但在执行(假)执行语句后返回代码.我可以想出很多方法来实现最终目标,但是他们都有更多的代码行和/或临时对象或函数的创建,我发现它们不够优雅.(注意这是VB.NET语法,但它不是VB语法问题,因为AFAIK C#会有同样的问题.)

那么做我想做的事最干净的方法是什么?

编辑:人们已经问过我正在使用什么ORM,但这真的是一个普通的LINQ问题; 我不是试图将其转换为逻辑以在服务器上运行,我只是想在服务器上运行查询后运行代码客户端一些语法糖.

Ufu*_*arı 11

您可以在投影结果时使用匿名类型.C#示例:

var items = from x In db.ChildTable
            join y In db.ParentTable on x.ParentId equals y.Id
            select new { Child =x , Parent=y };
Run Code Online (Sandbox Code Playgroud)

然后分配父属性.

foreach(var item in items)
{
    item.Child.Parent = item.Parent;
}

return items.Select(item => item.Child);
Run Code Online (Sandbox Code Playgroud)

此外,您可能希望使用一些ORM解决方案,而不是自己滚动.

  • @JoshuaFrank - 看来你正试图将副作用(设置属性)引入LINQ查询.LINQ(以及一般的函数式编程)不是为此而设计的.在"选择"或"添加后续foreach"中创建新实例(子类型或匿名类型). (4认同)

Jos*_*ank 2

这些建议,尤其是@Paul 的建议,非常有帮助,但我的最终版本足够不同,我将把它写成我自己的答案。

我实现了以下完全通用的扩展功能:

<Extension()> _
Public Function Apply(Of T)(ByVal Enumerable As IEnumerable(Of T), ByVal action As Action(Of T)) As IEnumerable(Of T)
    For Each item In Enumerable
        action(item)
    Next

    Return Enumerable
End Function
Run Code Online (Sandbox Code Playgroud)

这与 ForEach 相同,只不过它返回传入的序列,而且我认为Apply这个名称清楚地表明存在副作用。然后我可以将查询写为:

Dim Children = (
            From x In db.ChildTable
            Join y In db.ParentTable
            On x.ParentId Equals y.Id
            ).
            Apply(Sub(item) item.x.Parent = item.y).
            Select(Function(item) item.x)
Run Code Online (Sandbox Code Playgroud)

如果有一种方法可以使用自定义查询运算符,那当然会更好,这样我就不必使用 lambda 语法,但即便如此,这看起来也非常干净且可重用。再次感谢您的所有帮助。