.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。代码如下:

View Code
需要注意的是TotalCount属性,在分页情况下,是指查询语句在数据库中查询出的所有记录条数,而MicroDataTable的数据是当前页面的记录。
对于从数据库中获取DataTable的做法,采用类似SqlHelper的方式编写DbContext的ExecuteDataTable扩展方法,传入SQL语句和SQL语句的参数,生成MicroDataTable:
1publicstaticMicroDataTable ExecuteDataTable(thisDbContext context,stringsql,paramsobject[] parameters)2{3varconcurrencyDetector = context.Database.GetService();45using(concurrencyDetector.EnterCriticalSection())6{7varrawSqlCommand = context.Database.GetService().Build(sql, parameters);89RelationalDataReader query = rawSqlCommand.RelationalCommand.ExecuteReader(context.Database.GetService(), parameterValues: rawSqlCommand.ParameterValues);1011returnMicroDataTableHelper.FillDataTable(query.DbDataReader,0,int.MaxValue);12}13}1415publicstaticMicroDataTable ExecuteDataTable(thisDbContext context,stringsql,intpageIndex,intpageSize,paramsobject[] parameters)16{17varconcurrencyDetector = context.Database.GetService();1819using(concurrencyDetector.EnterCriticalSection())20{21varrawSqlCommand = context.Database.GetService().Build(sql, parameters);2223RelationalDataReader query = rawSqlCommand.RelationalCommand.ExecuteReader(context.Database.GetService(), parameterValues: rawSqlCommand.ParameterValues);2425returnMicroDataTableHelper.FillDataTable(query.DbDataReader,0,int.MaxValue);26}27}
这个方法还是需要部分.net framework core的技巧的,流程是根据SQL和参数创建原生的SQLCommand,执行ExecuteReader方法返回DataReader,再把DataReader填充到MicroDataTable中。注意的是,IConcurrencyDetector在.net core的描述是这样的:Thi