如何在 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 字段的目的来看是不正确的。
也许有非法的方法,但比我上面给出的方法更简单?
你有两种方法来解决这个问题。
- 使用您拥有的查询创建数据库级别的视图并在 entity framework 中使用它,然后您将能够简单地执行以下操作
var lst = db.vw_name.OrderBy(d => d.diff).ToList();
- 改为使用 LINQ Query Syntax,但您需要编写多个查询并将它们连接在一起,以及创建一个新的 class,查询可以使用它来实例化对象列表。这是一个不包含 SQL 函数
的简化示例
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()
并获得所需的列。
我有一些 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 字段的目的来看是不正确的。
也许有非法的方法,但比我上面给出的方法更简单?
你有两种方法来解决这个问题。
- 使用您拥有的查询创建数据库级别的视图并在 entity framework 中使用它,然后您将能够简单地执行以下操作
var lst = db.vw_name.OrderBy(d => d.diff).ToList();
- 改为使用 LINQ Query Syntax,但您需要编写多个查询并将它们连接在一起,以及创建一个新的 class,查询可以使用它来实例化对象列表。这是一个不包含 SQL 函数 的简化示例
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()
并获得所需的列。