在從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; } }