EFCore DbContext扩展执行原生SQL查询对象集合


EFCore扩展,让DbContext支持执行原生SQL语句并将结果转换为对象,同时支持原生上下文事务

C# 全选
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage;
using System.Data;
using System.Data.Common;

namespace JOC.EFCore
{

    /// <summary>
    /// 扩展
    /// </summary>
    public static class CustomDbContextExtensions
    {
        /// <summary>
        /// 执行 SQL 查询并返回自定义对象列表
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="context"></param>
        /// <param name="sql"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public static List<T> ExecuteSqlQuery<T>(this DbContext context, string sql, params object[] parameters) where T : class
        {
            var transaction = context.Database.CurrentTransaction;
            return ExecuteSqlQueryWithTransaction<T>(context, sql, transaction, parameters);
        }

        /// <summary>
        /// 执行 SQL 查询并返回单个自定义对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="context"></param>
        /// <param name="sql"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public static T? ExecuteSqlQuerySingle<T>(this DbContext context, string sql, params object[] parameters) where T : class
        {
            var transaction = context.Database.CurrentTransaction;
            return ExecuteSqlQuerySingleWithTransaction<T>(context, sql, transaction, parameters);
        }

        // 执行 SQL 查询并返回自定义对象列表(带事务)
        private static List<T> ExecuteSqlQueryWithTransaction<T>(DbContext context, string sql, IDbContextTransaction? transaction, params object[] parameters) where T : class
        {
            var connection = context.Database.GetDbConnection();
            List<T> results = new List<T>();

            try
            {
                connection.Open();

                var command = connection.CreateCommand();
                command.CommandText = sql;
                if (parameters.Length > 0)
                    command.Parameters.AddRange(parameters);
                command.Transaction = transaction?.GetDbTransaction();

                var flags = System.Reflection.BindingFlags.Public
                       | System.Reflection.BindingFlags.Instance
                       | System.Reflection.BindingFlags.IgnoreCase;
                var properties = typeof(T).GetProperties(flags);

                using (var reader = command.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        var entity = Activator.CreateInstance<T>();

                        for (int i = 0; i < reader.FieldCount; i++)
                        {
                            string name = reader.GetName(i);
                            var p = properties.Where(w => w.Name.Equals(name, StringComparison.CurrentCultureIgnoreCase)).FirstOrDefault();
                            if (p != null)
                            {

                                p.SetValue(entity, CheckType(reader.GetValue(i), p.PropertyType), null);
                            }
                        }

                        results.Add(entity);
                    }
                }
            }
            finally
            {
                connection.Close();
            }

            return results;
        }

        // 执行 SQL 查询并返回单个自定义对象(带事务)
        private static T? ExecuteSqlQuerySingleWithTransaction<T>(DbContext context, string sql, IDbContextTransaction? transaction, params object[] parameters) where T : class
        {
            var results = ExecuteSqlQueryWithTransaction<T>(context, sql, transaction, parameters);
            return results.FirstOrDefault();
        }

        // <summary>
        /// 对可空类型进行判断转换(*要不然会报错)
        /// </summary>
        /// <param name="value">DataReader字段的值</param>
        /// <param name="conversionType">该字段的类型</param>
        /// <returns></returns>
        private static object? CheckType(object value, Type conversionType)
        {
            if (conversionType.IsGenericType && conversionType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
            {
                if (value == null || value == DBNull.Value)
                    return null;
                System.ComponentModel.NullableConverter nullableConverter = new System.ComponentModel.NullableConverter(conversionType);
                conversionType = nullableConverter.UnderlyingType;
            }
            return Convert.ChangeType(value, conversionType);
        }

    }

}
版权声明:本文为YES开发框架网发布内容,转载请附上原文出处连接
张国生
上一篇:C#多线程下载图片 URL转Image
下一篇:深入理解js中的yield
评论列表

发表评论

评论内容
昵称:
关联文章

EFCore DbContext扩展执行原生SQL查询对象集合
EFCore官方扩展
GZDBHelper中ExecuteDataReader方法,执行SQL语句,并返回指定对象集合
EFCore分组查询Group使用
EFCore数据库提供程序
JOC.EFCore使用
GZDBHelper中GetDataSet方法,执行SQL语句,返回DataSet结构
Redis OM .NET Redis对象映射框架
GZDBHelper中GetTable方法,执行SQL语句,返回DataTable结构
GZDBHelper中ExecuteScalar方法,执行SQL语句,返回第一行第一列
SQL Server 查询参数管理类
GZDBHelper中HasRow方法,执行SQL语句,判断是否有返回数据
EFCore生成实体带上注释
.Net 线程安全集合
WPF对象级资源
DbDataReader转对象
Linq to SQL语句基础讲解
.NET 通用多条件动态参数查询方法 - SqlSugar ORM
SQL表数据多的时候创建索引失败,提示:- 无法创建索引“idx_**”。执行超时已过期。完成操作之前已超时或服务器未响应。
MSSQL 常用查询集成工具 SQLServerTools

联系我们
联系电话:15090125178(微信同号)
电子邮箱:garson_zhang@163.com
站长微信二维码
微信二维码