如何使用Entity Framework Core 2.1执行SqlQuery?

Jun*_*ior 13 entity-framework entity-framework-6 entity-framework-core

在Entity Framework 6中,我可以使用以下命令在数据库上执行原始SQL查询:

IEnumerable<string> Contact.Database.SqlQuery<string>("SELECT a.title FROM a JOIN b ON b.Id = a.aId WHERE b.Status = 10");
Run Code Online (Sandbox Code Playgroud)

在一个新项目中,我正在尝试使用Entity Framework Core 2.1.我需要执行原始SQL查询.谷歌搜索时,我可以看到扩展名SqlQuery已更改为FromSql.但是,FromSql只存在于DbSet<>不上DbContext.Database.

FromSql该如何在外面跑DbSet<>?该方法FromSql在数据库对象上不存在DbContext.Database.FromSql<>.

Cod*_*und 20

我可以看到扩展SqlQuery已更改为FromSql

但是这种新FromSql方法比...更具有分解性SqlQuery.该方法的文档解释了它存在一些限制,如:

SQL查询只能用于返回属于模型的实体类型.我们的待办事项上有一项增强功能,可以从原始SQL查询中返回特殊类型.

SQL查询必须返回实体或查询类型的所有属性的数据.

[...]

因此,在您的情况下,您正在使用的SQL查询如下:

SELECT a.title FROM a JOIN b ON b.Id = a.aId WHERE b.Status = 10
Run Code Online (Sandbox Code Playgroud)

由于文档说,你只能使用FromSql实体或查询类型.您的SQL查询不会返回模型中定义的实体的所有数据,但它只返回实体的一列.顺便说一下,EF Core 2.1中引入了一项新功能,该功能自2018年7月7日起在候选版本中发布.微软称:

EF Core 2.1 RC1是一个"上线"版本,这意味着一旦您测试了您的应用程序与RC1正常工作,您可以在生产中使用它并获得Microsoft的支持,但是一旦可用,您仍应更新到最终的稳定版本.

在查询类型上使用FromSql

什么是查询类型:

EF Core模型现在可以包含查询类型.与实体类型不同,查询类型没有在其上定义的键,也不能插入,删除或更新(即它们是只读的),但它们可以通过查询直接返回.查询类型的一些使用场景是:映射到没有主键的视图,映射到没有主键的表,映射到模型中定义的查询,作为FromSql()查询的返回类型

如果要对SQL文本使用查询类型功能,首先要定义一个类,让我们为它命名MySuperClass:

public class MySuperClass
{
    public string Title { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

然后在你的DbContext类中定义了DbQuery<MySuperClass>类似下面的类型的属性:

public DbQuery<MySuperClass> MySuperQuery { get; set; }
Run Code Online (Sandbox Code Playgroud)

最后你可以使用FromSql它,如下所示:

var result = context.MySuperQuery.FromSql("SELECT a.title FROM a JOIN b ON b.Id = a.aId WHERE b.Status = 10").ToList().First();
var title = result.Title;
Run Code Online (Sandbox Code Playgroud)

不想用 DbQuery<T>

如果你不想使用DbQuery<T>并且不想定义只包含一个属性的类,那么你可以在他的回答中使用ExecuteSqlCommandAsync像@ vivek nuna那样的(他的回答是部分正确的).但是您必须知道该方法返回的值是您的查询所影响的行数.此外,您必须将标题作为输出参数,以便将查询作为存储过程.使用ExecuteSqlCommandAsyncExecuteSqlCommand之后读取调用方法时传递的输出参数.

一种更简单的方法,无需创建存储过程,因此不使用ExecuteSqlCommandAsync或使用ExecuteSqlCommand以下代码:

using (var context = new MyDbContext())
{
    var conn = context.Database.GetDbConnection();
    await conn.OpenAsync();
    var command = conn.CreateCommand();
    const string query = "SELECT a.title FROM a JOIN b ON b.Id = a.aId WHERE b.Status = 10";
    command.CommandText = query;
    var reader = await command.ExecuteReaderAsync();
    while (await reader.ReadAsync())
    {
        var title = reader.GetString(0);
        // Do whatever you want with title 
    }
}  
Run Code Online (Sandbox Code Playgroud)

您可以使此逻辑成为一个辅助方法,它将接收您的SQL查询并返回所需的数据.但我建议你使用Dapper.Net whcih包含很多帮助方法,这些方法将有助于像我们上面那样轻松处理RAW SQL并与之共享smae连接DbContext.


viv*_*una 2

您可以通过以下方式使用在程序集类ExecuteSqlCommandAsync中定义的方法。RelationalDatabaseFacadeExtensionsMicrosoft.EntityFrameworkCore.Relational

_databaseContext.Database.ExecuteSqlCommandAsync(<Your parameters>)
Run Code Online (Sandbox Code Playgroud)

  • 只执行SQL,不返回结果集 (11认同)