.net core可以执行SQL语句,但是只能生成强类型的返回结果。例如var blogs = context.Blogs.FromSql("SELECT * FROM dbo.Blogs").ToList()。而不允许返回DataSet、DataTable等弱类型。可能由于这个原因没有实现在.net core中DataTable,然而DataTable还是可能会用到的。我们这里就有一个数据仓库的需求,允许用户自行编写类似SQL语句,然后执行,以表格展示。因为语句是千变万化的,因此我也不知道用户的语句输出的是啥,更无法以类型来定义,因此只能采用DataTable方式。
之前.net framework下,可以通过dataadpater很方便的填充datatable,然后将datatable的数据推送到客户端展示。但是.net core下,已经没有DataTable和DataSet,我们只能自行实现MicroDataTable。
这里我们也按照DataTable的方式,MicroDataTable的列定义为MicroDataColumn,行定义为MicroDataRow。代码如下:
public class MicroDataTable{ /// <summary>/// 整个查询语句结果的总条数,而非本DataTable的条数/// </summary>public int TotalCount { get; set; }public List<MicroDataColumn> Columns { get; set; } = new List<MicroDataColumn>();public List<MicroDataRow> Rows { get; set; } = new List<MicroDataRow>();public MicroDataColumn[] PrimaryKey { get; set; }public MicroDataRow NewRow(){return new MicroDataRow(this.Columns, new object[Columns.Count]);}}public class MicroDataColumn{public string ColumnName { get; set; }public Type ColumnType { get; set; }}public class MicroDataRow{private object[] _ItemArray;public List<MicroDataColumn> Columns { get; private set; }public MicroDataRow(List<MicroDataColumn> columns, object[] itemArray){this.Columns = columns;this._ItemArray = itemArray;}public object this[int index]{get { return _ItemArray[index]; }set { _ItemArray[index] = value; }}public object this[string columnName]{get{int i = 0;foreach (MicroDataColumn column in Columns){if (column.ColumnName == columnName)break;i++;}return _ItemArray[i];}set{int i = 0;foreach (MicroDataColumn column in Columns){if (column.ColumnName == columnName)break;i++;}_ItemArray[i] = value;}}}
需要注意的是TotalCount属性,在分页情况下,是指查询语句在数据库中查询出的所有记录条数,而MicroDataTable的数据是当前页面的记录。
对于从数据库中获取DataTable的做法,采用类似SqlHelper的方式编写DbContext的ExecuteDataTable扩展方法,传入SQL语句和SQL语句的参数,生成MicroDataTable:
public static MicroDataTable ExecuteDataTable(this DbContext context, string sql, params object[] parameters){var concurrencyDetector = context.Database.GetService<IConcurrencyDetector>();using (concurrencyDetector.EnterCriticalSection()){var rawSqlCommand = context.Database.GetService<IRawSqlCommandBuilder>().Build(sql, parameters);RelationalDataReader query = rawSqlCommand.RelationalCommand.ExecuteReader(context.Database.GetService<IRelationalConnection>(), parameterValues: rawSqlCommand.ParameterValues);return MicroDataTableHelper.FillDataTable(query.DbDataReader, 0, int.MaxValue);}}public static MicroDataTable ExecuteDataTable(this DbContext context, string sql, int pageIndex, int pageSize, params object[] parameters){var concurrencyDetector = context.Database.GetService<IConcurrencyDetector>();using (concurrencyDetector.EnterCriticalSection()){var rawSqlCommand = context.Database.GetService<IRawSqlCommandBuilder>().Build(sql, parameters);RelationalDataReader query = rawSqlCommand.RelationalCommand.ExecuteReader(context.Database.GetService<IRelationalConnection>(), parameterValues: rawSqlCommand.ParameterValues);return MicroDataTableHelper.FillDataTable(query.DbDataReader, 0, int.MaxValue);}}
新闻热点
疑难解答
图片精选