Asp.net core 如何在实体框架核心中运行存储过程?

Asp.net core 如何在实体框架核心中运行存储过程?,asp.net-core,asp.net-core-mvc,entity-framework-core,Asp.net Core,Asp.net Core Mvc,Entity Framework Core,我正在ASP.NET Core应用程序中使用EF Core 1.0。您能告诉我执行存储过程的正确方法吗?带有ObjectParameters和((IOObjectContextAdapter)this.ObjectContext.ExecuteFunction的旧方法不起作用。存储过程支持尚未在EF7中实现(从7.0.0-beta3开始)。您可以使用issue跟踪此功能的进度 现在,您可以使用ADO.NET以老式的方式进行操作 var connection=(SqlConnection)cont

我正在ASP.NET Core应用程序中使用EF Core 1.0。您能告诉我执行存储过程的正确方法吗?带有
ObjectParameters
((IOObjectContextAdapter)this.ObjectContext.ExecuteFunction
的旧方法不起作用。

存储过程支持尚未在EF7中实现(从7.0.0-beta3开始)。您可以使用issue跟踪此功能的进度

现在,您可以使用ADO.NET以老式的方式进行操作

var connection=(SqlConnection)context.Database.AsSqlServer().connection.DbConnection;
var command=connection.CreateCommand();
command.CommandType=CommandType.storedProcess;
command.CommandText=“MySproc”;
command.Parameters.AddWithValue(“@MyParameter”,42);
command.ExecuteNonQuery();
“(SqlConnection)上下文”
--这种类型的铸造不再有效。您可以执行以下操作:
“SqlConnection context;

“.AsSqlServer()”
--不存在

“command.ExecuteNonQuery();“
--不返回结果。
reader=command.ExecuteReader()
有效


使用dt.load(reader)…然后您必须将框架从5.0切换到4.51,因为5.0还不支持数据表/数据集。注意:这是VS2015 RC。

现在解决了EF Core 1.0中对存储过程的支持,这也支持多个结果集的映射

你可以用c这样称呼它#


我在使用
ExecuteSqlCommand
ExecuteSqlCommandAsync
时遇到了很多麻烦,IN参数很容易,OUT参数很难

我不得不恢复使用
DbCommand
这样-

DbCommand cmd = _context.Database.GetDbConnection().CreateCommand();

cmd.CommandText = "dbo.sp_DoSomething";
cmd.CommandType = CommandType.StoredProcedure;

cmd.Parameters.Add(new SqlParameter("@firstName", SqlDbType.VarChar) { Value = "Steve" });
cmd.Parameters.Add(new SqlParameter("@lastName", SqlDbType.VarChar) { Value = "Smith" });

cmd.Parameters.Add(new SqlParameter("@id", SqlDbType.BigInt) { Direction = ParameterDirection.Output });

我在中写了更多关于它的内容。

目前EF 7或EF Core不支持在designer中导入存储过程并直接调用它们的旧方法。您可以查看路线图以了解将来将支持什么:

因此,现在最好使用SqlConnection调用存储过程或任何原始查询,因为此作业不需要整个EF。以下是两个示例:

在本例中,调用返回单个value.String的存储过程

CREATE PROCEDURE [dbo].[Test]
    @UserName nvarchar(50)
AS
BEGIN
    SELECT 'Name is: '+@UserName;
END
调用返回列表的存储过程

CREATE PROCEDURE [dbo].[TestList]
AS
BEGIN
    SELECT [UserName], [Id] FROM [dbo].[AspNetUsers]
END
要调用这些存储过程,最好创建包含所有这些函数的静态类,例如,我将其称为DataAccess类,如下所示:

public static class DataAccess

    {
        private static string connectionString = ""; //Your connection string
        public static string Test(String userName)
        {
            using (SqlConnection conn = new SqlConnection(connectionString))
            {
                conn.Open();

                // 1.  create a command object identifying the stored procedure
                SqlCommand cmd = new SqlCommand("dbo.Test", conn);

                // 2. set the command object so it knows to execute a stored procedure
                cmd.CommandType = CommandType.StoredProcedure;

                // 3. add parameter to command, which will be passed to the stored procedure
                cmd.Parameters.Add(new SqlParameter("@UserName", userName));

                // execute the command
                using (var rdr = cmd.ExecuteReader())
                {
                    if (rdr.Read())
                    {
                        return rdr[0].ToString();
                    }
                    else
                    {
                        return null;
                    }
                }
            }
        }

        public static IList<Users> TestList()
        {
            using (SqlConnection conn = new SqlConnection(connectionString))
            {
                conn.Open();

                // 1.  create a command object identifying the stored procedure
                SqlCommand cmd = new SqlCommand("dbo.TestList", conn);

                // 2. set the command object so it knows to execute a stored procedure
                cmd.CommandType = CommandType.StoredProcedure;

                // execute the command
                using (var rdr = cmd.ExecuteReader())
                {
                    IList<Users> result = new List<Users>();
                    //3. Loop through rows
                    while (rdr.Read())
                    {
                        //Get each column
                        result.Add(new Users() { UserName = (string)rdr.GetString(0), Id = rdr.GetString(1) });
                    }
                    return result;
                }
            }

        }
    }
顺便说一句,您不必担心为每个sql请求打开和关闭连接的性能,因为asp.net会为您管理这些请求。
我希望这会有所帮助。

要执行存储过程,请使用执行原始SQL查询的方法

e、 g

var-products=context.products
.FromSql(“执行dbo.GetProducts”)
.ToList();
与参数一起使用

var result = _context.DBSetName.FromSql($"call storedProcedureName({optionalParam1})").ToList(); 
var productCategory=“电子”;
var product=context.Products
.FromSql(“执行dbo.GetProductByCategory{0}”,productCategory)
.ToList();

var productCategory=新的SqlParameter(“productCategory”、“Electronics”);
var product=context.product
.FromSql(“执行dbo.GetProductByName@productCategory”,productCategory)
.ToList();
执行原始SQL查询或存储过程有一定的限制。不能将其用于INSERT/UPDATE/DELETE。如果要执行INSERT、UPDATE、DELETE查询,请使用EXECUTESQL命令

var categoryName=“Electronics”;
dataContext.Database
.ExecuteSqlCommand(“dbo.InsertCategory@p0”,categoryName);

EF Core中对存储过程的支持与早期版本的EF code first类似

您需要通过从EF中插入DbContext类来创建DbContext类。存储过程正在使用DbContext执行

public static DbCommand LoadStoredProc(
  this DbContext context, string storedProcName)
{
  var cmd = context.Database.GetDbConnection().CreateCommand();
  cmd.CommandText = storedProcName;
  cmd.CommandType = System.Data.CommandType.StoredProcedure;
  return cmd;
}
第一步是编写一个从DbContext创建DbCommand的方法

public static DbCommand LoadStoredProc(
  this DbContext context, string storedProcName)
{
  var cmd = context.Database.GetDbConnection().CreateCommand();
  cmd.CommandText = storedProcName;
  cmd.CommandType = System.Data.CommandType.StoredProcedure;
  return cmd;
}
要将参数传递给存储过程,请使用以下方法

public static DbCommand WithSqlParam(
  this DbCommand cmd, string paramName, object paramValue)
{
  if (string.IsNullOrEmpty(cmd.CommandText))
    throw new InvalidOperationException(
      "Call LoadStoredProc before using this method");
  var param = cmd.CreateParameter();
  param.ParameterName = paramName;
  param.Value = paramValue;
  cmd.Parameters.Add(param);
  return cmd;
}
最后,要将结果映射到自定义对象列表,请使用MapToList方法

private static List<T> MapToList<T>(this DbDataReader dr)
{
  var objList = new List<T>();
  var props = typeof(T).GetRuntimeProperties();

  var colMapping = dr.GetColumnSchema()
    .Where(x => props.Any(y => y.Name.ToLower() == x.ColumnName.ToLower()))
    .ToDictionary(key => key.ColumnName.ToLower());

  if (dr.HasRows)
  {
    while (dr.Read())
    {
      T obj = Activator.CreateInstance<T>();
      foreach (var prop in props)
      {
        var val = 
          dr.GetValue(colMapping[prop.Name.ToLower()].ColumnOrdinal.Value);
          prop.SetValue(obj, val == DBNull.Value ? null : val);
      }
      objList.Add(obj);
    }
  }
  return objList;
}
私有静态列表映射列表(此DbDataReader dr)
{
var objList=新列表();
var props=typeof(T).GetRuntimeProperties();
var colMapping=dr.GetColumnSchema()
.Where(x=>props.Any(y=>y.Name.ToLower()==x.ColumnName.ToLower())
.ToDictionary(key=>key.ColumnName.ToLower());
如果(哈斯罗博士)
{
while(dr.Read())
{
T obj=Activator.CreateInstance();
foreach(道具中的var道具)
{
var val=
dr.GetValue(colMapping[prop.Name.ToLower()].ColumnOrdinal.Value);
prop.SetValue(对象,val==DBNull.Value?null:val);
}
objList.Add(obj);
}
}
返回对象列表;
}
现在,我们已经准备好使用ExecuteStoredProc方法执行存储过程,并将其映射到a列表,该列表的类型作为T传入

public static async Task<List<T>> ExecuteStoredProc<T>(this DbCommand command)
{
  using (command)
  {
    if (command.Connection.State == System.Data.ConnectionState.Closed)
    command.Connection.Open();
    try
    {
      using (var reader = await command.ExecuteReaderAsync())
      {
        return reader.MapToList<T>();
      }
    }
    catch(Exception e)
    {
      throw (e);
    }
    finally
    {
      command.Connection.Close();
    }
  }
}
公共静态异步任务ExecuteStoredProc(此DbCommand命令)
{
使用(命令)
{
if(command.Connection.State==System.Data.ConnectionState.Closed)
command.Connection.Open();
尝试
{
使用(var reader=await command.ExecuteReaderAsync())
{
返回reader.MapToList();
}
}
捕获(例外e)
{
投掷(e);
}
最后
{
command.Connection.Close();
}
}
}
例如,要执行一个名为“StoredProcedureName”的存储过程,其中包含两个名为“firstparamname”和“secondparamname”的参数,这就是实现

List<MyType> myTypeList = new List<MyType>();
using(var context = new MyDbContext())
{
  myTypeList = context.LoadStoredProc("StoredProcedureName")
  .WithSqlParam("firstparamname", firstParamValue)
  .WithSqlParam("secondparamname", secondParamValue).
  .ExecureStoredProc<MyType>();
}
List myTypeList=newlist();
使用(var context=new MyDbContext())
{
myTypeList=context.LoadStoredProc(“StoredProcedureName”)
.WithSqlParam(“firstparamname”,firstParamValue)
.WithSqlParam(“secondparamname”,secondParamValue)。
.ExecureStoredProc();
}

如果您正在执行stor
var spresult = _informixContext.procdata.FromSql("EXECUTE PROCEDURE dummyproc ({0},{1},{2})", parameters: new[] { p0, p1,p2 }).ToList();
var result = _context.DBSetName.FromSql($"call storedProcedureName()").ToList(); 
var result = _context.DBSetName.FromSql($"call storedProcedureName({optionalParam1})").ToList(); 
public partial class JobScheduleSmsEntities : DbContext
{
    public JobScheduleSmsEntities()
        : base("name=JobScheduleSmsEntities")
    {
        Database.SetInitializer<JobScheduleSmsEntities>(new CreateDatabaseIfNotExists<JobScheduleSmsEntities>());
    }

    public virtual DbSet<Customer> Customers { get; set; }
    public virtual DbSet<ReachargeDetail> ReachargeDetails { get; set; }
    public virtual DbSet<RoleMaster> RoleMasters { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        //modelBuilder.Types().Configure(t => t.MapToStoredProcedures());

        //modelBuilder.Entity<RoleMaster>()
        //     .HasMany(e => e.Customers)
        //     .WithRequired(e => e.RoleMaster)
        //     .HasForeignKey(e => e.RoleID)
        //     .WillCascadeOnDelete(false);
    }
    public virtual List<Sp_CustomerDetails02> Sp_CustomerDetails()
    {
        //return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction<Sp_CustomerDetails02>("Sp_CustomerDetails");
        //  this.Database.SqlQuery<Sp_CustomerDetails02>("Sp_CustomerDetails");
        using (JobScheduleSmsEntities db = new JobScheduleSmsEntities())
        {
           return db.Database.SqlQuery<Sp_CustomerDetails02>("Sp_CustomerDetails").ToList();

        }

    }

}
public partial class Sp_CustomerDetails02
{
    public long? ID { get; set; }
    public string Name { get; set; }
    public string CustomerID { get; set; }
    public long? CustID { get; set; }
    public long? Customer_ID { get; set; }
    public decimal? Amount { get; set; }
    public DateTime? StartDate { get; set; }
    public DateTime? EndDate { get; set; }
    public int? CountDay { get; set; }
    public int? EndDateCountDay { get; set; }
    public DateTime? RenewDate { get; set; }
    public bool? IsSMS { get; set; }
    public bool? IsActive { get; set; }
    public string Contact { get; set; }
}
List<Model> rows = null;

ctx.LoadStoredProc("dbo.ListAll")
   .AddParam("limit", 300L)
   .AddParam("limitOut", out IOutParam<long> limitOut)
   .Exec(r => rows = r.ToList<Model>());

long limitOutValue = limitOut.Value;

ctx.LoadStoredProc("dbo.ReturnBoolean")
   .AddParam("boolean_to_return", true)
   .ReturnValue(out IOutParam<bool> retParam)
   .ExecNonQuery();

bool b = retParam.Value;

ctx.LoadStoredProc("dbo.ListAll")
   .AddParam("limit", 1L)
   .ExecScalar(out long l);
public class MySPModel
{
    public int Id {get; set;}
    public string Name {get; set;}
}
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
        ...
}
var result = await _context.Query<MySPModel>().AsNoTracking().FromSql(string.Format("EXEC {0} {1}", functionName, parameter)).ToListAsync();
/// <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();
}
namespace MikesBank.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class ResetController : ControllerBase
    {
        private readonly MikesBankContext _context;

        public ResetController(MikesBankContext context)
        {
            _context = context;
        }

        [HttpGet]
        public async Task<ActionResult> Get()
        {
            try
            {
                using (DbConnection conn = _context.Database.GetDbConnection())
                {
                    if (conn.State != System.Data.ConnectionState.Open)
                        conn.Open();
                    var cmd = conn.CreateCommand();
                    cmd.CommandText = "Reset_Data";
                    await cmd.ExecuteNonQueryAsync();
                }
                return new OkObjectResult(1);
            }
            catch (Exception ex)
            {
                return new BadRequestObjectResult(ex.Message);
            }
        }
    }
}
public class MyContextContext : DbContext
{
    public virtual DbQuery<CheckoutInvoiceModel> CheckoutInvoice { get; set; } 
}
public async Task<IEnumerable<CheckoutInvoiceModel>> GetLabReceiptByReceiptNo(string labReceiptNo)
{
    var listing = new List<CheckoutInvoiceModel>();
    try
    {
        var sqlCommand = $@"[dbo].[Checkout_GetLabReceiptByReceiptNo] {labReceiptNo}";
        
        listing = await db.Set<CheckoutInvoiceModel>().FromSqlRaw(sqlCommand).ToListAsync();                       
                        
    }
    catch (Exception ex)
    {
        return null;
    }
    return listing;
}
modelBuilder.Entity<ResultData>(e =>
        {
            e.HasNoKey();
        });
public async Task<IEnumerable<ResultData>> GetDetailsData(int id, string name)
{
    var pId = new SqlParameter("@Id", id);
  var pName = new SqlParameter("@Name", name);
    return await _context.Set<ResultData>()
             .FromSqlRaw("Execute sp_GetDeailsData  @Id @Name", parameters: new[] { pId, pName })
            .ToArrayAsync();
}
ConfigureServices(IServiceCollection services){
    services.AddDbContext<AppDbContext>(opt => opt
                   .UseSqlServer(Configuration.GetConnectionString("SampleConnectionString")));
    services.AddScoped<ISomeDAL, SomeDAL>();

}
            
    public  class AppDbContext : DbContext{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
    {}
}
public class SomeDAL : ISomeDAL
{
     private readonly AppDbContext context;

     public SomeDAL(AppDbContext context)
         {
             this.context = context;
         }
     public  GetPropertiesResponse GetAllPropertiesByCity(int CityId)
     {
         //Create Required Objects for response 
         //wont support ref Objects through params
         context.LoadStoredProc(SQL_STATEMENT)
            .AddParam("CityID", CityId).Exec( r =>
             {
                  while (r.Read())
                  {

                       ORMapping<GenericRespStatus> orm = new  ORMapping<GenericRespStatus>();
                       orm.AssignObject(r, _Status);
                  }

                  if (r.NextResult())
                  {

                       while (r.Read())
                       {
                           Property = new Property();
                           ORMapping<Property> orm = new ORMapping<Property>();
                           orm.AssignObject(r, Property);
                           _propertyDetailsResult.Add(Property);
                       }
                  }    
           });
    return new GetPropertiesResponse{Status=_Status,PropertyDetails=_propertyDetailsResult}; 
    }
}

public class GetPropertiesResponse
{
     public GenericRespStatus Status;
     public List<Property> PropertyDetails;
     public GetPropertiesResponse()
         {
             PropertyDetails = new List<Property>();
         }
}
public class GenericRespStatus
{
     public int ResCode { get; set; }
     public string ResMsg { get; set; }
}
internal class ORMapping<T>
{
    public void AssignObject(IDataReader record, T myClass)
    {
        PropertyInfo[] propertyInfos = typeof(T).GetProperties();
        for (int i = 0; i < record.FieldCount; i++)
        {
            if (propertyInfos.Any(obj => obj.Name == record.GetName(i))) //&& record.GetValue(i) != DBNull.Value
            {
                propertyInfos.Single(obj => obj.Name == record.GetName(i)).SetValue(myClass, Convert.ChangeType(record.GetValue(i), record.GetFieldType(i)));
            }
        }
    }
}