C# 如何将多个表中的数据集与EF Core中的某些列连接起来?

C# 如何将多个表中的数据集与EF Core中的某些列连接起来?,c#,entity-framework,linq,entity-framework-core,ef-core-2.0,C#,Entity Framework,Linq,Entity Framework Core,Ef Core 2.0,所以我有悲伤的调查和有趣的调查,它们都记录在各自的表格中。每个都附有审计数据。因此,调查在审计表中的记录中包含一个外键 我正在建立一个网页,列出所有已提交的调查。调查Id、用户名和提交日期 我来自MySQL/MSSQL的背景,我会这样写: SELECT s.Id, u.Name, a.SubmittedOn FROM sadSurveys s LEFT JOIN audits a ON s.AuditId = a.Id LEFT JOIN users u ON s.UserId = u.Id U

所以我有悲伤的调查和有趣的调查,它们都记录在各自的表格中。每个都附有审计数据。因此,调查在审计表中的记录中包含一个外键

我正在建立一个网页,列出所有已提交的调查。调查Id、用户名和提交日期

我来自MySQL/MSSQL的背景,我会这样写:

SELECT s.Id, u.Name, a.SubmittedOn
FROM sadSurveys s
LEFT JOIN audits a ON s.AuditId = a.Id
LEFT JOIN users u ON s.UserId = u.Id
UNION
SELECT f.Id, u.Name, a.SubmittedOn
FROM funSurveys f
LEFT JOIN audits a ON f.AuditId = a.Id
LEFT JOIN users u ON f.UserId = t.Id
然而,使用EF,到目前为止,我有这个

var allSurveys = _context.Audits
            .Include(f => f.FunSurvey)
                .ThenInclude(u => u.User)
            .Include(s => s.SadSurvey)
                .ThenInclude(u => u.User)
            .ToList();
…但我不知道如何将其映射回DTO,因为用户名/名称跨不同的调查对象,这取决于它与哪个调查相关,而且它变得越来越混乱,这让我认为我的EF代码没有使用正确的方法


我也不希望获取调查和审计中的所有列,因为这是一种浪费,返回的数据远远多于所需的数据。

使用查询语法的等效LINQ查询与SQL查询几乎相同(考虑到LINQ的细节):

但是,ORM和导航属性允许您通过更简单的LINQ查询实现相同的结果:

var allSurveys = ( 
    from s in _context.SadSurveys
    select new SurveyDTO { Id = s.Id, Name = s.User.Name, SubmittedOn = s.Audit.SubmittedOn }
    ).Concat(
    from s in _context.FunSurveys
    select new SurveyDTO { Id = s.Id, Name = s.User.Name, SubmittedOn = s.Audit.SubmittedOn })
    ).ToList();

我难以置信地感激这一点,并因此减少了对林克的恐惧,因为这很容易!我被告知不要在我的存储库中使用DTO,而只在控制器中将实体映射到DTO。但我认为这可能只是为了阻止我在存储库而不是控制器中编写映射代码逻辑。这可能会侥幸成功,因为它直接将数据返回到DTO。此外,现实情况是,我有更多的调查表要加入,还有两倍多的列要返回,因此,
select new SurveyDTO
行被重复了很多次-有什么方法可以改进吗?最简单的方法是为包含公共原语和导航属性的调查创建基类。然后子查询可以封装在一个受约束的泛型方法中。
var allSurveys = ( 
    from s in _context.SadSurveys
    select new SurveyDTO { Id = s.Id, Name = s.User.Name, SubmittedOn = s.Audit.SubmittedOn }
    ).Concat(
    from s in _context.FunSurveys
    select new SurveyDTO { Id = s.Id, Name = s.User.Name, SubmittedOn = s.Audit.SubmittedOn })
    ).ToList();