.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 = 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);
}
}

这个方法还是需要部分.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 = 0;
int beginIndex = pageSize * pageIndex;
int endIndex = pageSize * (pageIndex + 1) - 1;
while (reader.Read())
{
object[] values = new object[reader.FieldCount];
if (!defined)
{
for (int i = 0; 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 = 0; i < fieldCount; i++)
{
table.Columns.Add(reader.GetName(i), reader.GetFieldType(i));
}
object[] values = new object[fieldCount];
int currentIndex = 0;
int startIndex = pageSize * pageIndex;
try
{
table.BeginLoadData();
while (reader.Read())
{
if (startIndex > currentIndex++)
continue;
if (pageSize > 0 && (currentIndex - startIndex) > pageSize)
break;
reader.GetValues(values);
table.LoadDataRow(values, true);
}
}
finally
{
table.EndLoadData();
try //lgy:由于连接阿里云ADS数据库cmd.Cancel()会报错,所以把错误忽略了。
{
cmd.Cancel();
}
catch
{
}
reader.Close();
}
}

以上所述是小编给大家介绍的.Net core下直接执行SQL语句并生成DataTable,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索.net
, datatable
core
coredata查询语句、coredata sql 语句、coredata 打印sql语句、实用sql语句大全、sql语句自动生成器,以便于您获取更多的相关知识。

时间: 2024-09-14 09:21:43

.Net core下直接执行SQL语句并生成DataTable的实现方法_实用技巧的相关文章

动态组合SQL语句方式实现批量更新的实例_实用技巧

Default.aspx 复制代码 代码如下: <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Index.aspx.cs" Inherits="Index" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w

Linq to SQL Delete时遇到问题的解决方法_实用技巧

1.1.   Code1: using (PubsDataContext pubsContent = new PubsDataContext()) {     pubsContent.Log = Console.Out;     Author author = pubsContent.Authors.Single(a => a.au_id == "111-11-1111");     pubsContent.Authors.DeleteOnSubmit(author);    

asp.net下使用Request.From获取非服务器控件的值的方法_实用技巧

复制代码 代码如下: <tr> <td>登录名:<input id="Text1" type="text" name="loginName" /><asp:Label ID="Label1" runat="server" Text="用户名已经存在"></asp:Label> </td> </tr> &l

asp.net下将页面内容导入到word模板中的方法_实用技巧

1,新建word模版,方法是找需要用程序填充的word文档,在需要输入的地方用"书签"(插入-->书签-->输入id-->ok)标记后保存既可. 2,在word模版上修改安全添加everyone 可读,以防文件无法打开. 3,在工程里添加"引用"找到"Microsoft Word 10.0 Object Library"或"Microsoft Word 11.0 Object Library"点确定. 4,新

Yii框架在页面输出执行sql语句以方便调试的实现方法_php实例

本文实例讲述了Yii框架在页面输出执行sql语句以方便调试的实现方法.分享给大家供大家参考.具体分析如下: 我们使用:yiidebugtb来调试(因为用他界面比较美观,不影响界面其他元素). 1.下载yiidebugtb,并且放入到 application.extensions.yiidebugtb 目录 2.修改main.php,加入如下代码: 复制代码 代码如下: 'log'=>array(     'class'=>'CLogRouter',     'routes'=>array

Shell脚本中执行sql语句操作mysql的5种方法_linux shell

对于自动化运维,诸如备份恢复之类的,DBA经常需要将SQL语句封装到shell脚本.本文描述了在Linux环境下mysql数据库中,shell脚本下调用sql语句的几种方法,供大家参考.对于脚本输出的结果美化,需要进一步完善和调整.以下为具体的示例及其方法. 1.将SQL语句直接嵌入到shell脚本文件中 复制代码 代码如下: --演示环境  [root@SZDB ~]# more /etc/issue  CentOS release 5.9 (Final)  Kernel \r on an \

asp.net使用DataGridTree实现下拉树的方法_实用技巧

本文实例讲述了asp.net使用DataGridTree实现下拉树的方法.分享给大家供大家参考.具体实现方法如下: 下拉树实现原理:输出json到客户端,客户端实现动态加载,中间不会和服务端交互.数据量支持上经测试几千还是很快的.本下拉树控件是用c#+js树实现. 2.c# 计算器 计算字符串数学表达式源码 计算数学表达式原理 采用c#实现 很实用 //a.建立两个栈:第一个位操作数栈,第二个操作符符栈!(将栈定义为string类型) //b.对数字来说是无条件压入数字栈中. //c.而对符号来

详解在ASP.NET Core中使用Angular2以及与Angular2的Token base身份认证_实用技巧

Angular2是对Angular1的一次彻底的,破坏性的更新. 相对于Angular1.x,借用某果的广告语,唯一的不同,就是处处都不同. •首先,推荐的语言已经不再是Javascript,取而代之的TypeScript,(TypeScript = ES6 + 类型系统 + 类型注解), TypeScriipt的类型系统对于开发复杂的单页Web app大有帮助,同时编译成javascript后的执行效率也比大多数手写javascript要快.有兴趣的同学可以查阅官方文档:英文传送门 |中文传送

在asp.net(c#)下实现调用cmd的方法_实用技巧

下面以ping 为例用到命名空间System.Diagnostics: System.Diagnostics 命名空间 包含了能够与系统进程 事件日志 和性能计数器进行交互的类 一般用于帮助诊断和调试应用程序 例如 Debug类用于帮组调试代码 Process类能够控制进程访问 Trace类能够跟踪代码的执行情况 Process 用于操作本地或者远程进程打访问 通过Process 可以在托管环境下很容易的操作对外部进程的启动或者停止 . 复制代码 代码如下: using System; usin