using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; using System.Data; using System.Data.Common; using System.Data.SqlClient; using System.Linq; using System.Reflection; using System.Threading; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.Extensions.DependencyInjection; namespace Holder.ERP.System.Services { /// <summary> /// EF扩展 /// </summary> public static class EFExtension {/// <summary> /// 返回查询的数据 /// </summary> /// <typeparam name="T">数据类型</typeparam> /// <param name="context">数据上下文</param> /// <param name="sql">sql语句</param> /// <param name="parameters">slq参数</param> /// <returns></returns> public static async Task<IEnumerable<T>> ExecuteReaderAsync<T>(this DbContext context, RawSqlString sql, params object[] parameters) where T : new() { var relationalDataReader = await ExecuteReaderAsync(context.Database, sql, parameters.ToArray()); var reader = relationalDataReader.DbDataReader; var properties = typeof(T).GetProperties(); var result = new List<T>(); while (reader.Read()) { var row = new Dictionary<string, object>(); for (var fieldCount = 0; fieldCount < reader.FieldCount; fieldCount++) { row.Add(reader.GetName(fieldCount), reader[fieldCount]); } var data = new T(); foreach (var prop in properties) { if (row.TryGetValue(prop.Name, out object value)) { prop.SetValue(data, value == DBNull.Value ? null : value); } } result.Add(data); } reader.Close(); return result; } public static async Task<RelationalDataReader> ExecuteReaderAsync( this DatabaseFacade databaseFacade, RawSqlString sql, IEnumerable<object> parameters, CancellationToken cancellationToken = default(CancellationToken)) { using (await databaseFacade.GetService<IConcurrencyDetector>().EnterCriticalSectionAsync(cancellationToken)) { RawSqlCommand rawSqlCommand = databaseFacade.GetRelationalService<IRawSqlCommandBuilder>().Build(sql.Format, parameters); return await rawSqlCommand.RelationalCommand.ExecuteReaderAsync(databaseFacade.GetRelationalService<IRelationalConnection>(), rawSqlCommand.ParameterValues, cancellationToken); } } private static TService GetRelationalService<TService>( this IInfrastructure<IServiceProvider> databaseFacade) { TService service = databaseFacade.Instance.GetService<TService>(); if (service != null) return service; throw new InvalidOperationException(RelationalStrings.RelationalNotInUse); } } }