ead*_*dam 49 entity-framework-core asp.net-core-mvc asp.net-core
我在asp.net核心应用程序中使用EF7(实体框架核心).能否请您指出执行存储过程的正确方法?旧的方法与ObjectParameters和((IObjectContextAdapter)this).ObjectContext.ExecuteFunction不工作.
Arv*_*vin 61
现在解决了对EF7中存储过程的支持,这也支持多个结果集的映射.
你可以这样称呼它 - var userType = dbContext.Set().FromSql("dbo.SomeSproc @Id = {0}, @Name = {1}", 45, "Ada");
bri*_*lam 20
存储过程支持尚未在EF7中实现(从7.0.0-beta3开始).您可以使用问题#245跟踪此功能的进度.
现在,您可以使用ADO.NET以传统方式执行此操作.
var connection = (SqlConnection)context.Database.AsSqlServer().Connection.DbConnection;
var command = connection.CreateCommand();
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "MySproc";
command.Parameters.AddWithValue("@MyParameter", 42);
command.ExecuteNonQuery();
Run Code Online (Sandbox Code Playgroud)
Roh*_*ith 18
要执行存储过程,请使用执行RAW SQL查询的FromSql方法
例如
var products= context.Products
.FromSql("EXECUTE dbo.GetProducts")
.ToList();
Run Code Online (Sandbox Code Playgroud)
用于参数
var productCategory= "Electronics";
var product = context.Products
.FromSql("EXECUTE dbo.GetProductByCategory {0}", productCategory)
.ToList();
Run Code Online (Sandbox Code Playgroud)
要么
var productCategory= new SqlParameter("productCategory", "Electronics");
var product = context.Product
.FromSql("EXECUTE dbo.GetProductByName @productCategory", productCategory)
.ToList();
Run Code Online (Sandbox Code Playgroud)
执行RAW SQL查询或存储过程有一些限制.您不能将它用于INSERT/UPDATE/DELETE.如果要执行INSERT,UPDATE,DELETE查询,请使用ExecuteSqlCommand
var categoryName = "Electronics";
dataContext.Database
.ExecuteSqlCommand("dbo.InsertCategory @p0", categoryName);
Run Code Online (Sandbox Code Playgroud)
Mar*_*ero 10
EF Core 中对存储过程的支持类似于早期版本的 EF Code first。
您需要通过从 EF 继承 DbContext 类来创建 DbContext 类。存储过程使用 DbContext 执行。
第一步是编写一个从 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;
}
Run Code Online (Sandbox Code Playgroud)
要将参数传递给存储过程,请使用以下方法。
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;
}
Run Code Online (Sandbox Code Playgroud)
最后,使用 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;
}
Run Code Online (Sandbox Code Playgroud)
现在我们已准备好使用 ExecuteStoredProc 方法执行存储过程并将其映射到类型为 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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
例如,要执行一个名为“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>();
}
Run Code Online (Sandbox Code Playgroud)
我尝试了所有其他解决方案,但对我不起作用。但是我找到了一个合适的解决方案,它可能对这里的人有所帮助。
要调用存储过程并将结果放入 EF Core 中的模型列表,我们必须遵循 3 个步骤。
第 1 步。
您需要添加一个新类,就像您的实体类一样。其中应该具有 SP 中所有列的属性。例如,如果您的 SP 返回两列调用Id,Name那么您的新类应该类似于
public class MySPModel
{
public int Id {get; set;}
public string Name {get; set;}
}
Run Code Online (Sandbox Code Playgroud)
第2步。
然后您必须DbQuery为您的 SP添加一个属性到您的 DBContext 类中。
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
...
}
Run Code Online (Sandbox Code Playgroud)
第 3 步。
现在,您将能够从 DBContext 调用并从 SP 获取结果。
var result = await _context.Query<MySPModel>().AsNoTracking().FromSql(string.Format("EXEC {0} {1}", functionName, parameter)).ToListAsync();
Run Code Online (Sandbox Code Playgroud)
我正在使用通用的 UnitOfWork & Repository。所以我执行 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();
}
Run Code Online (Sandbox Code Playgroud)
希望对某人有帮助!!!
令人尴尬的是,缺乏这方面的文档。
我花了很多时间和尝试才弄清楚这一点,所以我想在这里记录下来,这样其他人就不必花时间来弄清楚这一点。我在用着Entity Framework Core Version 6.0.10。
有两种返回结果的存储过程。调用它们并获取结果的方法也各不相同。
返回基于表的输出的 SP。
在输出参数中返回输出的 SP。
如果你的 SP 看起来像这样:
CREATE PROCEDURE dbo.MyTestSPToGetShopType @ShopId AS VARCHAR(25)
AS
SELECT ShopId, ShopType
FROM Shop
WHERE SHOPID = @ShopId
Run Code Online (Sandbox Code Playgroud)
第 1 步: 根据您的输出创建一个类
public class MyTestSpResult
{
public string ShopId { get; set; }
public string ShopType { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
第 2 步:
在 DbContext 的方法中注册protected override void OnModelCreating(ModelBuilder builder):
builder.Entity<MyTestSpResult>(e => e.HasNoKey());
Run Code Online (Sandbox Code Playgroud)
步骤3: 从代码中调用SP,并得到结果:
var myTestSpResult = await _dbContext.Set<MyTestSpResult>()
.FromSqlInterpolated($"EXEC dbo.MyTestSPToGetShopType @ShopId = \"A03\"")
.ToArrayAsync();
var myShopType = myTestSpResult[0].ShopType;
Run Code Online (Sandbox Code Playgroud)
步骤1和2与上面相同。
步骤 3: 在 DbContext 中注册步骤 1 中的类:
public virtual DbSet<MyTestSpResult> MyTestSpResult { get; set; }
Run Code Online (Sandbox Code Playgroud)
第四步: 从代码中调用SP,并得到结果:
var mySPResult = await _dbContext.MyTestSpResult
.FromSqlInterpolated($"EXEC dbo.MyTestSPToGetShopType @ShopId = \"A03\"")
.ToArrayAsync();
var myShopType = mySPResult[0].ShopType;
Run Code Online (Sandbox Code Playgroud)
如果你的 SP 看起来像这样:
CREATE PROCEDURE dbo.MyOtherTestSPToGetShopType
(
@ShopId VARCHAR(25), @ShopType VARCHAR(25) OUTPUT
)
AS
SELECT @ShopType = ShopType
FROM Shop
WHERE SHOPID = @ShopId
Run Code Online (Sandbox Code Playgroud)
步骤 1: 创建 SQL 参数:
var shopId = new SqlParameter()
{
ParameterName = "@ShopId",
Value = "A03",
Direction = System.Data.ParameterDirection.Input,
SqlDbType = System.Data.SqlDbType.VarChar,
Size = 25
};
var shopType = new SqlParameter()
{
ParameterName = "@ShopType",
Direction = System.Data.ParameterDirection.Output,
SqlDbType = System.Data.SqlDbType.VarChar,
Size = 25
};
Run Code Online (Sandbox Code Playgroud)
步骤 2: 使用这些参数从代码中调用 SP,并获取结果:
await _dbContext.Database
.ExecuteSqlInterpolatedAsync($"EXEC dbo.MyOtherTestSPToGetShopType @ShopId = {shopId}, @ShopType = {shopType} OUT");
var myShopType = shopType.Value as string;
Run Code Online (Sandbox Code Playgroud)
小智 5
"(SqlConnection)context"
-- 这种类型转换不再有效。你可以做:"SqlConnection context;
".AsSqlServer()"
- 不存在。
"command.ExecuteNonQuery();"
-- 不返回结果。 reader=command.ExecuteReader()确实有效。
使用 dt.load(reader)... 那么您必须将框架从 5.0 切换回 4.51,因为 5.0 尚不支持数据表/数据集。注意:这是VS2015 RC。
我有很多的麻烦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 });
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
85059 次 |
| 最近记录: |