【问题标题】:How to make an SQL query with custom columns in Entity Framework Core 5如何在 Entity Framework Core 5 中使用自定义列进行 SQL 查询
【发布时间】:2021-02-28 06:00:14
【问题描述】:

我有一些这样的表:

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 表达式返回它们之间差距最大的两个分数。查询被执行并返回单行(从 lst.Count() 和调试器得知)。

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

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

也许有一些非法的方法,但比我上面给出的方法还少?

【问题讨论】:

    标签: c# sql sqlite orm entity-framework-core


    【解决方案1】:

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

    1. 使用您拥有的查询在数据库级别创建一个视图并在实体框架中使用它,然后您将能够简单地执行以下操作
    var lst = db.vw_name.OrderBy(d => d.diff).ToList();
    
    1. 请改用LINQ Query Syntax,但您需要编写多个查询并将它们连接在一起,以及创建一个新类,该查询可用于实例化对象列表。这是一个不包含 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();
    

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

    【讨论】:

    • 问题是我想返回一些不符合源类结构的东西(这就是示例中的查询所做的)。我不想创建一个正确对象的模仿(返回一个等同于table_names 的结构),因为这会导致难以捕捉的错误。
    【解决方案2】:

    除了answer from Bassel Ashi

    使用您拥有的查询在数据库级别创建一个视图并在实体框架中使用它

    在数据库级别创建视图:

    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");
    

    然后你需要创建一个类:

    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() 并获取所需的列。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-08-30
      • 2019-05-31
      • 1970-01-01
      • 1970-01-01
      • 2022-09-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多