4.5 .net core下直接执行SQL语句并生成DataTable
.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 = ;
- foreach (MicroDataColumn column in Columns)
- {
- if (column.ColumnName == columnName)
- break;
- i++;
- }
- return _ItemArray[i];
- }
- set
- {
- int i = ;
- 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, , 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, , int.MaxValue);
- }
- }
这个方法还是需要部分.net framework core的技巧的,流程是根据SQL和参数创建原生的SQLCommand,执行ExecuteReader方法返回DataReader,再把DataReader填充到MicroDataTable中。注意的是,IConcurrencyDetector在.net core的描述是这样的:This API supports the Entity Framework Core infrastructure and is not intended to be used directly from your code. This API may change or be removed in future releases。我们只能先这样实现,以后看是否ef.core能否改变或者给出更好的方式。
上面程序中,最后有一句话MicroDataTableHelper.FillDataTable,这个方法的主要功能是从DataReader填充到MicroDataTable的。
- public static MicroDataTable FillDataTable(DbDataReader reader, int pageIndex, int pageSize)
- {
- bool defined = false;
- MicroDataTable table = new MicroDataTable();
- int index = ;
- int beginIndex = pageSize * pageIndex;
- int endIndex = pageSize * (pageIndex + ) - ;
- while (reader.Read())
- {
- object[] values = new object[reader.FieldCount];
- if (!defined)
- {
- for (int i = ; i < reader.FieldCount; i++)
- {
- MicroDataColumn column = new MicroDataColumn()
- {
- ColumnName = reader.GetName(i),
- ColumnType = reader.GetFieldType(i)
- };
- table.Columns.Add(column);
- }
- defined = true;
- }
- if (index >= beginIndex && index <= endIndex)
- {
- reader.GetValues(values);
- table.Rows.Add(new MicroDataRow(table.Columns, values));
- }
- index++;
- }
- table.TotalCount = index;
- return table;
- }
上面这个程序,是按部就班的写法,效率应该不太高。最近时间紧,没有分析原先的Datatable装载方式,以后有时间优化吧。下面给出一个当时用.net framework从datareader获取分页数据到datatable的程序,仅作参考。当时这段程序使用了table.beginloaddata/endloaddata方式,效率明显有提升。
- using (IDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection))
- {
- int fieldCount = reader.FieldCount;
- for (int i = ; i < fieldCount; i++)
- {
- table.Columns.Add(reader.GetName(i), reader.GetFieldType(i));
- }
- object[] values = new object[fieldCount];
- int currentIndex = ;
- int startIndex = pageSize * pageIndex;
- try
- {
- table.BeginLoadData();
- while (reader.Read())
- {
- if (startIndex > currentIndex++)
- continue;
- if (pageSize > && (currentIndex - startIndex) > pageSize)
- break;
- reader.GetValues(values);
- table.LoadDataRow(values, true);
- }
- }
- finally
- {
- table.EndLoadData();
- try //lgy:由于连接阿里云ADS数据库cmd.Cancel()会报错,所以把错误忽略了。
- {
- cmd.Cancel();
- }
- catch
- {
- }
- reader.Close();
- }
- }
4.5 .net core下直接执行SQL语句并生成DataTable的更多相关文章
- .net core下直接执行SQL语句并生成DataTable
.net core可以执行SQL语句,但是只能生成强类型的返回结果.例如var blogs = context.Blogs.FromSql("SELECT * FROM dbo.Blogs& ...
- Entity Framework Core 执行SQL语句和存储过程
无论ORM有多么强大,总会出现一些特殊的情况,它无法满足我们的要求.在这篇文章中,我们介绍几种执行SQL的方法. 表结构 在具体内容开始之前,我们先简单说明一下要使用的表结构. public clas ...
- EF Core中执行Sql语句查询操作之FromSql,ExecuteSqlCommand,SqlQuery
一.目前EF Core的版本为V2.1 相比较EF Core v1.0 目前已经增加了不少功能. EF Core除了常用的增删改模型操作,Sql语句在不少项目中是不能避免的. 在EF Core中上下文 ...
- Dos命令提示符下 - 用sqlcmd执行*.sql语句
Dos命令提示符下 - 用sqlcmd执行*.sql语句 1)在Dos命令下执行sqlcmd命令(当然事先需要将sqlcmd增加到环境变量中去), 2)下面白色部分替换为服务器名或计算机名即可sqlc ...
- EF Core 执行SQL语句和存储过程
无论ORM有多么强大,总会出现一些特殊的情况,它无法满足我们的要求.在这篇文章中,我们介绍几种执行SQL的方法. 表结构 在具体内容开始之前,我们先简单说明一下要使用的表结构. public clas ...
- 使用Hive或Impala执行SQL语句,对存储在Elasticsearch中的数据操作(二)
CSSDesk body { background-color: #2574b0; } /*! zybuluo */ article,aside,details,figcaption,figure,f ...
- 使用Hive或Impala执行SQL语句,对存储在Elasticsearch中的数据操作
http://www.cnblogs.com/wgp13x/p/4934521.html 内容一样,样式好的版本. 使用Hive或Impala执行SQL语句,对存储在Elasticsearch中的数据 ...
- EFCore执行Sql语句的方法:FromSql与ExecuteSqlCommand
前言 在EFCore中执行Sql语句的方法为:FromSql与ExecuteSqlCommand:在EF6中的为SqlQuery与ExecuteSqlCommand,而FromSql和SqlQuery ...
- 使用Hive或Impala执行SQL语句,对存储在HBase中的数据操作
CSSDesk body { background-color: #2574b0; } /*! zybuluo */ article,aside,details,figcaption,figure,f ...
随机推荐
- PostGIS(解压版)安装
1.软件下载 postgresql-9.6.1-1-windows-x64-binaries.zip https://www.postgresql.org/download/windows/ post ...
- android Notification介绍
如果要添加一个Notification,可以按照以下几个步骤 1:获取NotificationManager: NotificationManager m_NotificationManager=(N ...
- 简历生成平台项目开发-STEP1问卷设计
周五课程结束完后,小组建立QQ群和微信群,着手讨论项目问题.一开始的大概想法:就业信息平台,收集企业招聘信息和就业生资料,提供给学生和企业的校企对接平台.后来发现群里谭卓同学也有个相关的思路,经过商量 ...
- (转)从0开始搭建SQL Server AlwaysOn 第二篇(配置故障转移集群)
原文地址: http://www.cnblogs.com/lyhabc/p/4682028.html 这一篇是从0开始搭建SQL Server AlwaysOn 的第二篇,主要讲述如何搭建故障转移集 ...
- php+websocket搭建简易聊天室实践
1.前言 公司游戏里面有个简单的聊天室,了解了之后才知道是node+websocket做的,想想php也来做个简单的聊天室.于是搜集各种资料看文档.找实例自己也写了个简单的聊天室. http连接分为短 ...
- nginx代理https站点(亲测)
nginx代理https站点(亲测) 首先,我相信大家已经搞定了nginx正常代理http站点的方法,下面重点介绍代理https站点的配置方法,以及注意事项,因为目前大部分站点有转换https的需要所 ...
- emmet,jade,haml, slim,less,sass,coffeescript等的实战优缺点
摘要: 文章背景,来自于群内周五晚上的一次头脑风暴式的思维碰撞交流活动. 随着前端技术的蓬勃发展, 各种新技术随着生产力的需要不断的涌入我们的视野, 那今天探讨的话题是这些新时代的前端兵器谱: 一. ...
- React-Native 动画优化
前言 动画对于客户端来说是非常重要的一部分,直接影响到应用的用户体验.前端对于动画优化通常使用CSS3样式来实现动画,以利用GPU加速特性.而React-Native由于渲染模式的不同,无法使用CSS ...
- Spring Batch在大型企业中的最佳实践
在大型企业中,由于业务复杂.数据量大.数据格式不同.数据交互格式繁杂,并非所有的操作都能通过交互界面进行处理.而有一些操作需要定期读取大批量的数据,然后进行一系列的后续处理.这样的过程就是" ...
- Java 序列化与反序列化
1.什么是序列化?为什么要序列化? Java 序列化就是指将对象转换为字节序列的过程,而反序列化则是只将字节序列转换成目标对象的过程. 我们都知道,在进行浏览器访问的时候,我们看到的文本.图片.音频. ...