【问题标题】:Using (linq?) with ef entities将 (linq?) 与 ef 实体一起使用
【发布时间】:2017-06-26 08:25:07
【问题描述】:

我有一个相当复杂的带有连接的 sql 语句。这是我使用 EF 的代码:

var MicrositeResponseAdors = _context.MicrositeResponseAdor
    .Include(user => user.UserTracking)
        .ThenInclude(tracking => tracking.AddTradeIn)
    .Include(user => user.UserTracking)
        .ThenInclude(tracking => tracking.TrackingFinance)
    .Include(user => user.UserTracking)
        .ThenInclude(tracking => tracking.SearchTracking)
    .Include(user => user.UserTracking)
        .ThenInclude(tracking => tracking.TrackingType)
    .Include(user => user.UserTracking)
        .ThenInclude(tracking => tracking.Vehicle)
    .FirstOrDefault(m => m.Id == id && m.FirstName.ToLower() != "test" && m.LastName.ToLower() != "test");

我需要将另一个联接添加到没有主键的表中,而 Entity Framework 不允许这样做。我什至无法伪造它。所以我被告知要使用我认为称为 LINQ 的东西来制作更自定义的东西?

我无法弄清楚如何使用原始 EF 实体类分配我的数据值。这是我目前所拥有的:

var MicrositeResponseAdors = (from p in _context.MicrositeResponseAdor
    join c in _context.UserTracking on p.Id equals c.UserTrackingId
    into pc
    select new {
        MicrositeResponseAdor = p, MicrositeResponseAdor.UserTracking = pc 
    }
).FirstOrDefault();

这给出了:

无效的匿名类型成员声明器。

我认为这是因为 MicrositeResponseAdor.UserTracking 的第一部分。我不确定如何在 MicrositeResponseAdor 下分配 UserTracking。

【问题讨论】:

  • 加入 ORM 是一种非常强烈的气味。 ORM 处理具有关系对象。 ORM 不是数据库,LINQ 也不是 SQL 的替代品。
  • 您需要向 MicroSiterResponseAdor 类添加另一个 relation。可能只是一个public UserTracking UserTracking {get;set;}。如果表、字段遵循它们似乎执行的约定,EF 将检测关系。查询根本不必更改
  • 顺便说一句,您发布的 EF 代码没有显示任何连接。仅加载一个 single 实体。所有那些Includes 强制加载,它们与连接毫无关系。如果您不需要急切加载,您甚至可以摆脱它们
  • 是的,使用 ORM 可以正常工作,但是我们必须添加另一个不存在的关系,该关系没有主键。由于时间限制和管理,我们目前无法修复它,因此我们需要临时解决方法,该解决方法不是使用 ORM,而是尝试通过 LINQ 加载它。至于 EF 和 Include,我很确定通过阅读其他文章,Include 在幕后的 SQL 中执行了 LEFT OUTER JOIN。我需要加入所有这些东西,再加上一个没有主键的东西。
  • 您误解了这些文章。 Include ONLY 用于强制加载。使用 LEFT 或 INNER 连接可能会也可能不会这样做,但您不能依赖于此。这样的策略确实从一个版本更改为另一个版本。如果没有关系,Include 只会引发错误。最后,如果您的select 需要来自相关类的数据,则可以生成JOIN。 ORM 可以做任何它认为合适的事情来返回你指定的结果。

标签: c# entity-framework linq-to-entities


【解决方案1】:

您给出的错误是 C# 编译错误,因为您尝试将属性命名为 MicrositeResponseAdor.UserTracking。属性名称不能包含点。

这至少可以编译:

var micrositeResponseAdor = (
    from p in _context.MicrositeResponseAdor
    join c in _context.UserTracking on p.Id equals c.UserTrackingId into pc
    select new {
        MicrositeResponseAdor = p,
        UserTracking = pc 
    }
).FirstOrDefault();

这将使您的UserTracking 出现在两个地方:

  1. micrositeResponseAdor.UserTracking
  2. micrositeResponseAdor.MicrositeResponseAdor.UserTracking

它在第一个是因为你把它放在那里,它在第二个是因为实体之间存在关系,所以如果 EF 在那个上下文中加载它,它可以方便地填充它(它有,因为你明确要求)。

因此您不必在查询中分配加载的导航属性,您只需确保已加载相关实体,无论是手动连接、Include 还是第二个查询。

问题是你为什么要这样做。您已经拥有Include 版本。 join 变体只是更冗长,但它没有添加任何内容。

并不是说 EF 总是在每个实体上都有一个键,无论数据库是否认为它是一个。从技术上讲,这与 Includejoin 无关。

【讨论】:

    猜你喜欢
    • 2021-02-16
    • 2014-02-05
    • 1970-01-01
    • 1970-01-01
    • 2014-09-23
    • 1970-01-01
    • 2018-04-09
    • 2017-02-19
    • 1970-01-01
    相关资源
    最近更新 更多