开发随笔记录——自定义DatabaseFacade的约定扩展类,实现自定义SQL查询返回数据(用于报表等复杂数据查询)。

 

声明:本文章将仅供保存以及参考,倘若涉及到利益问题,请联系博主进行删除,万分感谢。

前提:①本文章基于ASP.NET Core 3.1

   ②已安装Microsoft.EntityFrameworkCore、Microsoft.EntityFrameworkCore.SqlServer、Microsoft.EntityFrameworkCore.Tools

创建DatabaseFacade约定扩展类DbContextExtensions.class,如下代码:

public static class DbContextExtensions
    {
        private static void CombineParams(ref DbCommand command, params object[] parameters)
        {
            if (parameters != null)
            {
                foreach (SqlParameter parameter in parameters)
                {
                    if (!parameter.ParameterName.Contains("@"))
                        parameter.ParameterName = $"@{parameter.ParameterName}";
                    command.Parameters.Add(parameter);
                }
            }
        }

        private static DbCommand CreateCommand(DatabaseFacade facade, string sql, out DbConnection dbConn, params object[] parameters)
        {
            DbConnection conn = facade.GetDbConnection();
            dbConn = conn;
            conn.Open();
            DbCommand cmd = conn.CreateCommand();
            if (facade.IsSqlServer())
            {
                cmd.CommandText = sql;
                CombineParams(ref cmd, parameters);
            }
            return cmd;
        }

        public static DataTable SqlQuery(this DatabaseFacade facade, string sql, params object[] parameters)
        {
            DbCommand cmd = CreateCommand(facade, sql, out DbConnection conn, parameters);
            DbDataReader reader = cmd.ExecuteReader();
            DataTable dt = new DataTable();
            dt.Load(reader);
            reader.Close();
            conn.Close();
            return dt;
        }

        /// <summary>
        /// datatable转换为需要的类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static T Convert<T>(this DataTable dt)
        {
            if (dt == null) return default(T);
            string data = JsonConvert.SerializeObject(
                dt,
                Formatting.None,
                new DataTableConverter());
            return JsonConvert.DeserializeObject<T>(data);
        }

        /// <summary>
        /// DataTable转json字符串
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static string ConvertJson(this DataTable dt)
        {
            if (dt == null) return "";
            string data = JsonConvert.SerializeObject(
                dt,
                Formatting.None,
                new DataTableConverter());
            return data;
        }

        public static IEnumerable<T> SqlQuery<T>(this DatabaseFacade facade, string sql, params object[] parameters) where T : class, new()
        {
            DataTable dt = SqlQuery(facade, sql, parameters);
            return dt.ToEnumerable<T>();
        }

        public static IEnumerable<T> ToEnumerable<T>(this DataTable dt) where T : class, new()
        {
            PropertyInfo[] propertyInfos = typeof(T).GetProperties();
            T[] ts = new T[dt.Rows.Count];
            int i = 0;
            foreach (DataRow row in dt.Rows)
            {
                T t = new T();
                foreach (PropertyInfo p in propertyInfos)
                {
                    if (dt.Columns.IndexOf(p.Name) != -1 && row[p.Name] != DBNull.Value)
                        p.SetValue(t, row[p.Name], null);
                }
                ts[i] = t;
                i++;
            }
            return ts;
        }

       
    }

之后即可在开发环境中正常使用,如下:

_MyContext.Database.SqlQuery("select * from table").Convert<IEnumerable<object>>();
_MyContext.Database.SqlQuery<Table>("select * from table").ToList();

现在就可以用自己定义的SQL去查询复杂的数据源了。

上一篇:2021-2022-1 20211408 《信息安全专业导论》第九周学习总结


下一篇:Android冷启动优化,移动开发基础学习