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

C# 如何使用.NET CORE获得存储过程的实际结果?,c#,entity-framework,stored-procedures,.net-core,C#,Entity Framework,Stored Procedures,.net Core,只是在.NETCore上升级,遇到了一些无法解决的问题。 我有一个名为GetLeads的存储过程,其模式基本上返回 LEADID (INT) SALENO (INT) OFFICE (INT) PACKAGE (NVARCHAR(4) SALEDATE (DATETIME) 例如,在存储过程所在的同一数据库中,有一个名为Prospects的表。它的模式是 LEADID (INT) FNAME (NVARCHAR(50)) LNAME (NVARCHAR(50)) ADDR1 (NVARCHAR

只是在.NETCore上升级,遇到了一些无法解决的问题。 我有一个名为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");
也没有意义,因为它只返回受命令执行影响的记录数

因此,.NETCore中可用的FromSql方法显然有其局限性,尽管它被记录为可用于进行存储过程调用

理想情况下,我希望看到核心框架能够以与.NET框架中EF相同的方式直接调用存储过程和函数,并简化事情。但我意识到核心功能还不可用;尽管我希望它最终能实现

不管怎么说,别再胡扯了,切中要害了

在.NETCore中,在这些情况下,调用存储过程的最实用和最广泛接受的方法是什么?我知道ADO.NET是一种选择,但我严格按照使用EF的核心框架的范例来说,我要对Selvin的最后一句话表示感谢,因为它确实促使我找到了解决方案。但我真的需要一个明确的答案。 我还要感谢Rahul对使用Snickler作为替代方案所作的非常感谢的评论。但我想要一个解决方案,只涉及EF和.NETCore。老实说,所有的评论都非常感谢

因此,以下是始终能够使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中创建的存储过程实体模型作为虚拟数据库集添加到数据库上下文中。它应该位于由步骤1创建的Models目录中,并在名称前面加上单词“Context”

public virtual DbSet<Lead> Lead { get; set; }
注意:由于存储过程返回的记录集不需要主键,因此您可以:

  • 修改存储过程以包含主键,如标识字段
  • 在返回的记录集中标识几个字段,这些字段将构成可行的主键,并在模型中创建一个复合键
  • 然而,第二个选项需要一些额外的工作和考虑,因为您必须使用fluentapi来设置复合主键。EF Core不允许数据注释设置复合键


    希望此共享信息能够帮助其他遇到类似问题的人使用ExecuteOnQuery,并将cmd设置为:cmd.CommandType=System.Data.CommandType.storedProcess;关于
    \u ctx.Database.SqlQuery()
    ?@Selvin per EF DatabaseFacade不包含SqlQueryoh的定义。。。那么
    \u ctx.Query().FromSql()
    无法将“Microsoft.EntityFrameworkCore.Internal.InternalDbSet”类型的对象强制转换为“Microsoft.EntityFrameworkCore.DbQuery”类型呢。
    var _ctx = new DbContext();
    var pkgs = _ctx.Prospects.FromSql("EXEC dbo.GetPackages").ToList();