如何使用.NET CORE获得存储过程的实际结果?

时间:2019-07-16 11:28:20

标签: c# entity-framework stored-procedures .net-core

仅在.NET Core上启动并遇到一些无法解决的问题。 我有一个名为GetLeads的存储过程,该存储过程的模式基本上会返回

LEADID (INT)
SALENO (INT)
OFFICE (INT)
PACKAGE (NVARCHAR(4)
SALEDATE (DATETIME)

为了举例说明,存储过程所在的同一数据库中有一个表叫做Prospects。其架构为

LEADID (INT)
FNAME (NVARCHAR(50))
LNAME (NVARCHAR(50))
ADDR1 (NVARCHAR(150))
ADDR2 (NVARCHAR(150))
EMAIL (NVARCHAR(200))
PHONENO (NVARCHAR(200))
CONTACTDATE (DATETIME)

根据文档,我可以使用上下文模型的FromSql方法来调用存储过程。但是,如果存储过程返回的模式只有几个(如果有的话)字段与进行调用的上下文模型匹配,该怎么办?

如果我构造一个查询,例如:

var _ctx = new DbContext();
var pkgs = _ctx.Prospects.FromSql("EXEC dbo.GetPackages").ToList();

由于返回的记录集不包含与Prospects模型相关的字段,因此这显然将失败。

反之,则使用类似的内容:

var pkgs = _ctx.Database.ExecuteSqlCommand("EXEC dbo.GetPackages");

也是没有意义的,因为它只会返回受命令执行影响的记录数。

.NET Core中可用的FromSql方法显然有其局限性,尽管已记录为可用于进行存储过程调用。

理想情况下,我希望看到Core Framework能够以与.NET Framework中的EF几乎相同的方式直接调用存储过程和函数,并且可以简化事情。但是我意识到Core中还没有可用的功能。尽管我希望它最终会成功。

无论如何,足够的杂乱无章并指向重点。

在这些情况下,.NET Core中调用存储过程的最实用,最广泛接受的方法是什么?我知道ADO.NET是一个选择,但我严格来说是在使用EF的Core Framework范式内进行的

1 个答案:

答案 0 :(得分:0)

我将对Selvin的最后评论表示赞赏,因为它确实促使我寻求解决方案。但是我确实需要一个明确的答案。 我还要感谢Rahul关于使用Snickler作为替代方案的非常赞赏的评论。但是我想要一个只涉及EF和.NET Core的解决方案。老实说,所有评论都非常感激

因此,这是始终能够获取 FromSql 方法以在实体框架内使用存储过程所需的实际步骤。我使用的是使用MVC的“数据库优先”方法,但是该解决方案的整体方法无关紧要。

注意:如果已经创建EF上下文,则可以跳过步骤1。

步骤1:使用dotnet实用程序从数据库生成EntityFramework上下文和关联的实体模型。

dotnet ef dbcontext scaffold "Server=[YourDBServerName];Initial Catalog=[YourDatabaseName];Integrated Security=False;Persist Security Info=False;User ID=[YourUserId];Password=[YourUserPassword];" Microsoft.EntityFrameworkCore.SqlServer -o Models

步骤2::添加一个ViewModel,该ViewModel定义存储过程将返回的所有字段。注意:您可以替代地将其添加为模型,但是为了简洁起见并明确分离体系结构,我希望将存储过程实体与直接从数据库生成的模型区分开来。

同样重要的是,实体类必须具有主键,否则将不起作用。 EF要求所有实体都具有主键。

public partial class Lead
{
    [Key]
    public int leadid { get; set; }
    public int saleno { get; set; }
    public int office { get; set; }
    public string package { get; set; }
    public datetime saledate { get; set; }
}

步骤3:将在步骤2中创建的存储过程实体模型作为虚拟DbSet添加到数据库上下文中。该文件应位于第1步创建的Models目录中,名称前应加上“ Context”一词。

public virtual DbSet<Lead> Lead { get; set; }

执行完第2步和第3步之后,您可以使用Core Framework中的FromSql方法完成所有存储过程

var _ctx = new DbContext();
var pkgs = _ctx.Prospects.FromSql("EXEC dbo.GetPackages").ToList();

注意:由于从存储过程返回的记录集不需要主键,因此您可以:

  1. 修改存储过程以包括主键,例如身份字段
  2. 在返回的记录集中标识出将要构成的可行主键的几个字段,并在模型内创建一个复合键

但是第二个选项需要一些额外的工作和注意事项,因为您必须使用流利的API来设置复合主键。 EF Core不允许数据注释设置组合键。

希望这些共享信息将帮助其他走过相似问题的人