Asp.net core 如何在实体框架核心中运行存储过程?
我正在ASP.NET Core应用程序中使用EF Core 1.0。您能告诉我执行存储过程的正确方法吗?带有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
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)));
}
}
}
}