如何使用 Entity Framework Core 5.0 将复杂 SQL 查询的结果行映射到自定义 DTO?

Bjø*_*ard -1 c# sql-server entity-framework entity-framework-core .net-core

我有一个自定义且有些复杂的 SQL 查询,我需要通过 EF Core DbContext 执行该查询。

我意识到下面的示例代码可以使用简单的 .Select() 来解决,但不幸的是我的实际表格是通过魔术键连接的并且没有导航属性。

无论如何,我可以在不选择导航属性的情况下实现以下功能吗?

namespace ClassLibrary1
{
    public class MyService
    {
        private readonly MyContext _context;

        public void MyMethod()
        {
            var mySql = @"SELECT Foo.FooName, Bar.BarValue FROM Foo JOIN Bar ON Foo.Key = Bar.Key";
            List<Dto> dtoList = _context.Database.MethodImLookingFor<Dto>(mySql); // Any ideas?
        }
    }
    
    public class MyContext : DbContext
    {
        public DbSet<Foo> Foo { get; set; }
        public DbSet<Bar> Bar { get; set; }
    }

    // My models are only records for brevity.
    public record Foo(string Key, string FooName);
    public record Bar(string Key, string BarValue);
    public record Dto(string FooName, string BarValue);
}
Run Code Online (Sandbox Code Playgroud)

实际的SQL查询:

SELECT R.Id, S.Code, V.Code
FROM dbo.Results R
         JOIN dbo.Variable V ON V.Code = R.Value
         JOIN dbo.Severity S ON S.Id = V.SeverityId
WHERE R.Type = N'Type' AND S.Code = 'ABC' OR S.Code = 'CBA' AND R.Id = '123'
Run Code Online (Sandbox Code Playgroud)

我已经浏览了微软文档。如果不经过导航属性,这些都不会映射到自定义 DTO。

Ser*_*rge 5

稍微改变一下你的查询

SELECT R.Id, S.Code as Scode, V.Code as Vcode
FROM dbo.Results R
         JOIN dbo.Variable V ON V.Code = R.Value
         JOIN dbo.Severity S ON S.Id = V.SeverityId
WHERE R.Type = N'Type' AND S.Code = 'ABC' OR S.Code = 'CBA' AND R.Id = '123'
Run Code Online (Sandbox Code Playgroud)

为查询结果创建一个新类

[NotMapped]
public class SpResult
{
public int Id {get;set;}
public string Scode {get; set;}
public string Vcode {get; set;}
}
Run Code Online (Sandbox Code Playgroud)

添加到数据库上下文

 public virtual DbSet<SpResult> SpResults { get; set; }

 modelBuilder.Entity<SpResult>(e =>
   {
  e.HasNoKey();
   });
Run Code Online (Sandbox Code Playgroud)

最后编码

var spResult =  _context.SpResults.FromSqlRaw(mysql).ToList();

List<Dto> dtoList = spResult.Select( i=> new Dto
{
 ID = i.Id,
 FooName =i.Scode,
 BarValue=i.Vcode,
 
}).ToList();

Run Code Online (Sandbox Code Playgroud)