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);
}
}
}