我正在使用 Visual Studio 2017 实现 Asp.Net core Web API、实体框架核心、数据库优先方法。我已成功基于现有数据库生成上下文和类文件。我需要使用我的上下文访问存储过程。在实体框架的早期版本中,通过在向导中选择存储过程对象并生成包含这些对象的 edmx 很简单。然后,我可以通过实体框架公开的复杂类型对象访问存储过程。我如何在实体框架核心中做类似的事情。举个例子会有帮助吗?
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
但这不会得到你的存储过程。仍在进行中,跟踪问题 #245
但是,要执行存储过程,请使用执行原始 SQL 查询的 FromSql 方法
例如
var products= context.Products
.FromSql("EXECUTE dbo.GetProducts")
.ToList();
与参数一起使用
var productCategory= "Electronics";
var product = context.Products
.FromSql("EXECUTE dbo.GetProductByCategory {0}", productCategory)
.ToList();
或
var productCategory= new SqlParameter("productCategory", "Electronics");
var product = context.Product
.FromSql("EXECUTE dbo.GetProductByName @productCategory", productCategory)
.ToList();
执行 RAW SQL 查询或存储过程有一定的限制。您不能将其用于 INSERT/UPDATE/DELETE。如果要执行 INSERT、UPDATE、DELETE 查询,请使用 ExecuteSqlCommand
var categoryName = "Electronics";
dataContext.Database
.ExecuteSqlCommand("dbo.InsertCategory @p0", categoryName);
如果您希望结果集与已定义的任何对象相同,则在执行存储过程时,上面的示例可以正常工作。但是,如果您想要一个不受支持的结果集怎么办?据 EF Core 2 的开发人员称,这是一个即将到来的功能,但今天已经有了一个简单的解决方案。
创建您想要用于输出的模型。该模型将代表输出,而不是数据库中的表。
namespace Example.EF.Model
{
public class Sample
{
public int SampleID { get; set; }
public string SampleName { get; set; }
}
}
然后将一个新的 DBSet 与您的模型添加到您的上下文中:
public virtual DbSet<Sample> Sample { get; set; }
然后按照上面的操作,并使用您的模型作为输出:
var products = _samplecontext.Sample
.FromSql($"EXEC ReturnAllSamples {id}, {startdate}, {enddate}").ToList();
我希望这对任何人都有帮助。
我的原始帖子 - https://stackoverflow.com/a/57224037/1979465
要调用存储过程并将结果放入 EF Core 中的模型列表中,我们必须遵循 3 个步骤。
步骤1. 您需要添加一个新类,就像您的实体类一样。它应该具有 SP 中所有列的属性。例如,如果您的 SP 返回名为
Id
和 Name
的两列,那么您的新类应该类似于
public class MySPModel
{
public int Id {get; set;}
public string Name {get; set;}
}
第 2 步。
然后您必须在 SP 的 DBContext 类中添加一个
DbQuery
属性。
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
...
}
步骤 3.
现在您将能够从 DBContext 调用 SP 并获取结果。
var result = await _context.Query<MySPModel>()
.AsNoTracking()
.FromSql(string.Format("EXEC {0} {1}", functionName, parameter))
.ToListAsync();
我正在使用通用的工作单元和存储库。所以我执行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();
}
希望对某人有帮助!!!
我们在 EF Core 中执行存储过程来获取数据的解决方法是使用 FromSql 方法,您可以这样执行存储过程:
List<Employee> employees = dbcontext.Employee
.FromSql("GetAllEmployees").ToList();
但是对于创建、更新和删除,我们使用 ExecuteSqlCommand,如下所示:
var employee = "Harold Javier";
dbcontext.Employee
.ExecuteSqlCommand("InsertEmployee @emp", employee);
Rohith / Harold Javier / Sami 提供的解决方案有效。我想补充一点,您可以创建一个单独的 EF6 项目来生成结果集的 C# 类,然后将文件复制到您的 EFCore 项目。如果更改存储过程,您可以使用此处讨论的方法更新结果文件:存储过程和更新 EDMX
如果需要相应的 TypeScript 接口,可以安装这个 VS2017 扩展 TypeScript 定义生成器: https://marketplace.visualstudio.com/items?itemName=MadsKristensen.TypeScriptDefinitionGenerator
仍然有一些复制,但比手动创建类要简单。
编辑:有一个 VS2017 扩展用于生成 dbconext https://marketplace.visualstudio.com/items?itemName=ErikEJ.EFCorePowerTools。它不执行存储过程,但它提供了 VS 项目的右键菜单项,而不是命令行 Scaffold-DbContext。
如果您需要从 EntityFramework Core 执行 MySQL 数据库中的存储过程,则以下代码应该可以工作。
var blogTagId = 1;
var tags = await _dbContext.BlogTags.FromSqlRaw("CALL SP_GetBlogTags({0})", blogTagId).ToListAsync();