如何在 Entity Framework 核心 5 中使用自定义列进行 SQL 查询

How to make an SQL query with custom columns in Entity Framework Core 5

我有一些 table 这样的:

CREATE TABLE names (
    score   INTEGER NOT NULL PRIMARY KEY,
    name    TEXT NOT NULL
);

我想从中获取一些统计信息。在 sqlite 中我可以使用 LEAD,但不在那里。我现在关于 linq2db,但我不想使用它,因为它的算法。据我了解,这个包在EF linq中没有添加LEAD模板到SQL的转换,而是在自己这边执行LEAD算法(不是在数据库端,效率更高)。如果我错了,请纠正我。

比如我要执行查询:

var lst = db.table_names.FromSqlRaw("SELECT score, LEAD(cid, 1) OVER (ORDER BY score) as next, LEAD(score, 1) OVER (ORDER BY score) - score AS diff FROM names ORDER BY diff DESC LIMIT 1");

这个SQL-表示returns两个分数差距最大的。查询被执行并且 returns 一行(从 lst.Count() 和调试器得知)。

结果在那里,但我如何得到它?也许 EF 的某些功能允许合法地从自定义 SQL 格式的数据结构中获取数据?

我不想用我需要传输到代码的数据填充 class 结构,但从 class 字段的目的来看是不正确的。

也许有非法的方法,但比我上面给出的方法更简单?

你有两种方法来解决这个问题。

  1. 使用您拥有的查询创建数据库级别的视图并在 entity framework 中使用它,然后您将能够简单地执行以下操作
var lst = db.vw_name.OrderBy(d => d.diff).ToList();
  1. 改为使用 LINQ Query Syntax,但您需要编写多个查询并将它们连接在一起,以及创建一个新的 class,查询可以使用它来实例化对象列表。这是一个不包含 SQL 函数
  2. 的简化示例
public class Scores {
    public int Score { get; set; }
    public int Next { get; set; }
    public int Max { get; set; }
}

var lst = (from x in db.table_names
           orderby x.diff
           select new Scores {
               Score = x.score,
               Next = x.next,
               Max = x.Max
          }).ToList();

在我看来,出于多种原因,前一种方法要好得多。

除了

Create a view on the database level with the query you have and use it in the entity framework

创建数据库级别的视图:

db.Database.ExecuteSqlRaw(@"CREATE VIEW View_scoreDiff AS SELECT score, LEAD(cid, 1) OVER (ORDER BY score) as next, LEAD(score, 1) OVER (ORDER BY score) - score AS diff FROM names ORDER BY diff DESC LIMIT 1");

然后你需要创建一个class:

public class View_scoreDiffClass {
    public int Score { get; private set; }
    public int Next { get; private set; }
    public int Diff { get; private set; }
}

将下一个字段添加到您的上下文中:

public DbSet<View_scoreDiffClass> View_scoreDiff { get; private set; }

将以下行添加到 OnModelCreating:

modelBuilder.Entity<View_scoreDiffClass>().ToView("View_scoreDiff").HasNoKey();

完成所有这些之后,您可以执行 db.View_scoreDiff.FirstOrDefault() 并获得所需的列。