在从EF切换成EFCore2.0的过程中,遇到了存储过程的实现问题。
在EF中调用存储过程,非常方便,能够直接将结果转换成对应的结果类。 如代码中的Database.SqlQuery<TElement>()
public virtual List<StatsPlanCompleteAndAdjustItem> GetStatsPlanCompleteAndAdjustItem(DateTime minExecuteDate, DateTime maxExecuteDate, Guid organizationId) { var results = _dbContext.SqlQuery<StatsPlanCompleteAndAdjustItem> ("StatsPlanCompleteAndAdjustItem @minExecuteDate,@maxExecuteDate,@organizationId", new SqlParameter("minExecuteDate", minExecuteDate), new SqlParameter("maxExecuteDate", maxExecuteDate), new SqlParameter("organizationId", organizationId)).ToList(); return results; } public IEnumerable<TElement> SqlQuery<TElement>(string sql, params object[] parameters) { return this.Database.SqlQuery<TElement>(sql, parameters); }
然而,在EF Core2.0中还没有实现存储过程的调用,没有sqlquery<T>方法。
查找网上基本采用RawSql的方式来实现。but有局限,需要用dbcontext中的dbset<entity>.FromSql方法,返回值是List<entity>,为啥要借用dbset呢,这个方法纯粹借用表查询的方法,好多存储过程返回的未必是entity,不能将存储过程的结果转换成自己想要的数据类型,所以非常棘手。感觉 不是efcore调用 存储过程的思路。
using (var dataContext = new SampleDbContext()) { var categoryID = 1; var query = dataContext.Categories.FromSql($"GetCategoryById {categoryID}"); var result = query.ToList(); Assert.NotNull(result); }
采用第二思路,用传统的sqlCommand方法,执行存储过程,利用executeReader读取结果后,采用反射将数据转换成想要的泛型结果
作为积极吃ef core这个螃蟹的人,积极记录分享这个笔记,供其他朋友参考。感觉给力的话,赞助点红包哈
public virtual List<PerformancePlanCompleteAndAdjustItem> GetPerformancePlanCompleteAndAdjustItem(DateTime minExecuteDate, DateTime maxExecuteDate, Guid organizationId) { //注意直接只写存储过程名称,不用写参数名,跟原来写法不一样。 var results = _dbContext.SqlQuery<PerformancePlanCompleteAndAdjustItem> ("PerformancePlanCompleteAndAdjustItem", new SqlParameter("minExecuteDate", minExecuteDate), new SqlParameter("maxExecuteDate", maxExecuteDate), new SqlParameter("organizationId", organizationId)).ToList(); return results; }
public IEnumerable<TElement> SqlQuery<TElement>(string sql, params object[] parameters) where TElement:new () { var connection = Database.GetDbConnection(); using (var cmd = connection.CreateCommand()) { Database.OpenConnection(); cmd.CommandText = sql; cmd.CommandType = System.Data.CommandType.StoredProcedure; cmd.Parameters.AddRange(parameters); var dr =cmd.ExecuteReader(); var columnSchema = dr.GetColumnSchema(); var data = new List<TElement>();; while (dr.Read()) { TElement item = new TElement(); Type type = item.GetType(); foreach (var kv in columnSchema) { var propertyInfo = type.GetProperty(kv.ColumnName); if (kv.ColumnOrdinal.HasValue && propertyInfo != null) { //注意需要转换数据库中的DBNull类型 var value= dr.IsDBNull(kv.ColumnOrdinal.Value)?null:dr.GetValue(kv.ColumnOrdinal.Value); propertyInfo.SetValue(item, value); } } data.Add(item); } dr.Dispose(); return data; } }