【问题标题】:Join 5 tables using Lambda使用 Lambda 连接 5 个表
【发布时间】:2020-09-26 23:22:40
【问题描述】:

我正在尝试使用 lambda 来加入 5 个表。我想知道的是我是否做得对,是否有更好的方法。任何建议都非常感谢。

 var myList = _context.Event
            .Join(_context.EventHost,
                e => e.EventHostId,
                eh => eh.Id,
                (e, eh) => new { Event = e, EventHost = eh })
            .Join(_context.EventAddress,
                eh => eh.EventHost.EventAddressID,
                ea => ea.ID,
                (eh, ea) => new { EventAddress = ea, EventHost = eh })
            .Join(_context.OrderHeaderGroup,
                ea => ea.EventHost.Event.Id,
                ohg => ohg.EventId,
                (ea, ohg) => new { EventAddress = ea, OrderHeaderGroup = ohg })
            .Join(_context.OrderHeader,
                ohg => ohg.OrderHeaderGroup.OrderHeaderGroupID,
                oh => oh.OrderHeaderGroupID,
                (oh, ohg) => new { OrderHeader = oh, OrderHeaderGroup = ohg })
            .Select(c => new {
                c.OrderHeader.OrderHeaderGroup.EventId,
                c.OrderHeader.EventAddress.EventAddress.Name,
                c.OrderHeader.EventAddress.EventAddress.Phone,
                c.OrderHeader.EventAddress.EventAddress.Address1,
                c.OrderHeader.EventAddress.EventAddress.Address2,
                c.OrderHeader.EventAddress.EventAddress.City,
                c.OrderHeader.EventAddress.EventAddress.Country,
                c.OrderHeader.EventAddress.EventAddress.PostalCode,
                c.OrderHeader.EventAddress.EventAddress.Email,
                c.OrderHeader.EventAddress.EventHost.Event.ConsultantId,
                c.OrderHeader.EventAddress.EventHost.Event.StartDate,
                c.OrderHeader.EventAddress.EventHost.Event.EndDate,
            }).Where(x => x.ContactId == contactId && x.StartDate >= newStartDate && x.EndDate <= newEndDate).ToList();

【问题讨论】:

  • 我只想指出,查询语法会使每个连接中的中间投影变平,您也可以这样做。例如,第二个连接可以投影(xpi, ea) =&gt; new { EventAddress = ea, EventHost = xpi.EventHost, Event = xpi.Event })。这使得后续的连接和最终的投影更加清晰。 (xpi 代表"transparent identifier")。
  • 但是 Athanasios 是对的:使用查询语法。您在这里没有做任何需要您直接使用扩展方法的事情。
  • 并且,使用查询语法,您可以将where 子句放在它自然所属的位置,而无需支付编写冗长的x =&gt; x.OrderHeader.EventAddress.EventHost.Event.StartDate &gt;= newStartDate:where e.StartDate &gt;= newStartDate select ...) 的代价。胜利的透明标识符。

标签: c# lambda


【解决方案1】:

是的,按照 Microsoft 的建议使用查询语法:Check here

在编译时,查询表达式会根据 C# 规范中规定的规则转换为标准查询运算符方法调用。任何可以用查询语法表达的查询,也可以用方法语法表达。但是,在大多数情况下,查询语法更具可读性和简洁性

from event in _context.Event
join eventHost in _context.EventHost 
    on event.EventHostId equals eventHost.Id
join eventAddress in _context.EventAddress 
    on eventHost.EventAddressId equals eventAddress.Id
// etc
select new {/*You new anonymous type here*/}

【讨论】:

  • 谢谢!我已经厌倦了阅读 3 lambda 版本的 join。
  • 如果您使用 jank ORM 或不使用 ORM,这可能是必要的。但是在任何 Fluent ORM 中,你只是做错了。 Microsoft 是正确的,如果您有 SQL 头脑,并且如果您不了解 ORM 和编程的工作原理,那么查询语法更具可读性。但是如果你为任何流利的 ORM 学习 LinqToEntities,你可以做得更好。请注意您如何要求查询和选择的 //etc。所以你的答案看起来很干净,但这只是因为你把所有东西都漏掉了。如果你扩展它,它将看起来与 OP 几乎相同。那有什么用?
  • 甚至没有关闭。方法语法的连接很复杂,并且使您在后续连接中引用到查询语法的等效项。您需要阅读函数定义才能了解其中的内容。
【解决方案2】:

这里的问题不是优先的代码可读性。顺便说一句,我认为 Lambda 比 Query 形式更具可读性。但那是因为我是一名程序员。

问题在于您正试图从 SQL 开发人员的角度出发,并将其融入编程。当 LinqToEntities 第一次出现时,我就这样做了,从 SSMS 等开始,我编写了一个查询,然后我在 C# 中执行 Transliteration

解决方案是使用您的 ORM。如果您使用功能丰富的 ORM,您应该有一个名为 Navigation Properties 的东西。这些已经为您提供了隐式连接,这些连接要么是隐式的,要么是在 Fluent 映射中显式声明的。因此,您不必在每次编写 LINQ 语句时都重新描述每个连接。

如果您信任该语言并正确配置您的系统,您最终会得到如下结果:

// This is not shortened, this should be the whole thing.
var myList = _context.OrderHeader
.Where(x => x.EventAddress.Something.ContactId == contactId 
      && x.EventAddress.Something.StartDate >= newStartDate 
      && x.EventAddress.Something.EndDate <= newEndDate)
.Select(c => new DetailEntityView(c)).ToList();

我还建议使用“视图”类。这些不是配置为持久保存到 DB 的实体,而是类似于 C# 中的 DB 视图。它们是较少使用的类,仅传输数据。

public class DetailEntityView
{
    public int EventId { get; set; }
    public string Name { get; set; }
    // ... etc

    public DetailEntityView(OrderHeader c)
    {
        EventId = c.OrderHeaderGroup.EventId;
        Name = c.EventAddress.EventAddress.Name;
        // ... etc
    }
}

现在,一些 ORM 的功能不如世界上的 EF 和 NH。所以在这种情况下,很抱歉你或你的团队选择了其他东西。

此外,您的所有联接都在 ID 上,这是应该的。但是一些自定义查询加入不受约束的字段,例如名称字段或其他值。在这些情况下,您确实需要将这些特定连接添加到您的查询中。但是 1.) Ew。 2.) 为什么?并且 3.) 然后你可以做你在你的 OP 中所做的事情。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多