使用Entity框架核心生成和访问存储过程

Tom*_*Tom 13 entity-framework entity-framework-core asp.net-core

我正在使用Visual Studio 2017实现Asp.Net核心Web API,实体框架核心,数据库第一种方法.我已经设法基于现有数据库生成上下文和类文件.我需要使用我的上下文访问存储过程.在早期版本的实体框架中,通过在向导中选择存储过程对象并生成包含这些对象的edmx,可以很简单.然后,我可以通过实体框架公开的复杂类型对象访问存储过程.我如何在实体框架核心中做类似的事情.一个例子会有帮助吗?

Roh*_*ith 17

数据库第一种方法在EF Core中没有edmx文件.相反,你必须使用Scaffold-DbContext

安装Nuget包Microsoft.EntityFrameworkCore.Tools和Microsoft.EntityFrameworkCore.SqlServer.Design

Scaffold-DbContext "Server=(localdb)\mssqllocaldb;Database=Blogging;Trusted_Connection=True;" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models
Run Code Online (Sandbox Code Playgroud)

但这不会得到您的存储过程.它仍处于工作中,跟踪问题#245

但是,要执行存储过程,请使用执行RAW SQL查询的FromSql方法

例如

var products= context.Products
    .FromSql("EXECUTE dbo.GetProducts")
    .ToList();
Run Code Online (Sandbox Code Playgroud)

用于参数

var productCategory= "Electronics";

var product = context.Products
    .FromSql("EXECUTE dbo.GetProductByCategory {0}", productCategory)
    .ToList();
Run Code Online (Sandbox Code Playgroud)

要么

var productCategory= new SqlParameter("productCategory", "Electronics");

var product = context.Product
    .FromSql("EXECUTE dbo.GetProductByName  @productCategory", productCategory)
    .ToList();
Run Code Online (Sandbox Code Playgroud)

执行RAW SQL查询或存储过程有一些限制.您不能将它用于INSERT/UPDATE/DELETE.如果要执行INSERT,UPDATE,DELETE查询,请使用ExecuteSqlCommand

var categoryName = "Electronics";
dataContext.Database
           .ExecuteSqlCommand("dbo.InsertCategory @p0", categoryName);
Run Code Online (Sandbox Code Playgroud)


Sam*_*ami 9

如果您希望结果集与已定义的任何对象相同,则上述示例在执行存储过程时工作正常.但是如果你想要一个不受支持的结果集呢?根据EF Core 2的开发人员的说法,这将是一个功能,但现在已经有了一个简单的解决方案.

创建要用于输出的模型.此模型将表示输出,而不是数据库中的表.

namespace Example.EF.Model
{
    public class Sample
    {
        public int SampleID { get; set; }
        public string SampleName { get; set; }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在您的上下文中添加一个包含您的模型的新DBSet:

public virtual DbSet<Sample> Sample { get; set; }
Run Code Online (Sandbox Code Playgroud)

然后如上所述,并使用您的模型输出:

var products = _samplecontext.Sample
      .FromSql($"EXEC ReturnAllSamples {id}, {startdate}, {enddate}").ToList();
Run Code Online (Sandbox Code Playgroud)

我希望这可以帮助任何人.

  • 您可以将它们放在具有部分类的不同文件中,以使其更容易。 (2认同)
  • `EXEC ReturnAllSamples {id}, {startdate}, {enddate}` 将生成不带参数的 sql,并且可能受到 SQL 注入。当您尝试以这种方式执行过程时,.NET Core 会给出非常彻底的警告消息。最好使用接受的答案的方式`.FromSql("EXECUTE dbo.GetProductByCategory {0}", ProductCategory)` (2认同)

Abh*_*ine 6

我原来的帖子 - /sf/answers/4005682621/

要调用存储过程并将结果获取到 EF Core 中的模型列表中,我们必须遵循 3 个步骤。

步骤1. 您需要添加一个新类,就像您的实体类一样。它应该具有 SP 中所有列的属性。例如,如果您的 SP 返回调用的两列IdName那么您的新类应该类似于

public class MySPModel
{
    public int Id {get; set;}
    public string Name {get; set;}
}
Run Code Online (Sandbox Code Playgroud)

第2步。

然后,您必须DbQuery向 SP 的 DBContext 类添加一个属性。

public partial class Sonar_Health_AppointmentsContext : DbContext
{
        public virtual DbSet<Booking> Booking { get; set; } // your existing DbSets
        ...

        public virtual DbQuery<MySPModel> MySP { get; set; } // your new DbQuery
        ...
}
Run Code Online (Sandbox Code Playgroud)

步骤 3.

现在您将能够从 DBContext 调用 SP 并获取结果。

var result = await _context.Query<MySPModel>().AsNoTracking().FromSql(string.Format("EXEC {0} {1}", functionName, parameter)).ToListAsync();
Run Code Online (Sandbox Code Playgroud)

我正在使用通用的 UnitOfWork 和存储库。所以我执行SP的函数是

/// <summary>
/// Execute function. Be extra care when using this function as there is a risk for SQL injection
/// </summary>
public async Task<IEnumerable<T>> ExecuteFuntion<T>(string functionName, string parameter) where T : class
{
    return await _context.Query<T>().AsNoTracking().FromSql(string.Format("EXEC {0} {1}", functionName, parameter)).ToListAsync();
}
Run Code Online (Sandbox Code Playgroud)

希望它对某人有帮助!