繁体   English   中英

如何将 SQL 查询应用于 C# 数据表/数据集?

[英]How to apply SQL query to a C# DataTable/Dataset?

我有一个应用程序,用户可以在其中输入 sql 查询作为文本,我需要在我的应用程序中针对 C# DataTable/Dataset 运行它。 有可能吗?

编辑:根据答案,以及无法完成的更多研究 - 无法将 SQL 查询应用于您已经读入应用程序的表。 查看可能的解决方法的答案。

编辑 2:在我的案例中,最终的解决方案是使用 ANTLR 实现一个简单的解析器。 它允许用户使用“AND”和“OR”关键字以及括号输入简单的查询。 ANTLR 生成的 class 会将其转换为一组指令,然后我可以使用这些指令来查询 C# 数据集。

如果您的用户将输入除最简单的 select 语句之外的任何内容,您将很难做到这一点。 我想为您的项目编写一个完整的 SQL 解析器的成本会高得令人望而却步,但这基本上就是您所谈论的内容。

对于我们拥有的本土 ORM,我有一个类,它基本上将预定义的 SQL 查询转换为可以与DataTable.Select一起使用的内容,但 where 子句是从 SqlParameters 生成的。

可能的解决方案

也许您可以结合以下项目来接近您所追求的目标:

Linqer(SQL 到 LINQ 转换器)然后是LINQ 到 DataSet

我自己没用过Linqer。

其他一些想法

我相信您已经考虑过这一点,但这样做的难度可能意味着如果您缩小一点,可能会有更好的方法。 严格来说,使用未知查询查询缓存意味着您必须用所有可能的数据填充缓存,或者能够在提交查询时调用该数据。 根据定义,这不能提供比直接查询源更好的性能,除非您在缓存过期之前足够地访问缓存以使其值得。 对于临时报告系统(我的假设),我倾向于怀疑情况是否如此,而且我还担心它在除边缘情况之外的任何情况下都不会胜过数据库引擎。

@JoshC 还提到了 Sqlite 的可能性,还有 SQL Server 2012 LocalDB 可能符合要求,尽管这些肯定不是 .net 数据集。

如果要在应用程序中针对 c# 数据表/数据集运行搜索字符串

您可以在select方法中使用过滤器表达式。

myDataTable.Select("columnName1 like '%" + value + "%'");

其实有一个简单的解决办法。

  1. 将 DataTable 中的数据导出到 SQLite 内存数据库。
  2. 在 SQLite 内存数据库上运行 SQL。

这适用于将数据集导出到 SQLite:

$Data = <your DataSet>

$SQLiteConnection = [System.Data.SQLite.SQLiteConnection]::new('DataSource=:MEMORY:')
$SQLiteConnection.Open()

[System.String[]]$tableNames = $Data.Tables.TableName

foreach ($table in $tableNames) {
 $columnDefinitions = @()
 foreach ($column in $Data.Tables[$table].Columns) {
#  Ought to create mapping between Types and DBTypes AnsiString, Binary, Byte, Boolean, Currency, Date, DateTime, Decimal, Double, Guid, Int16, Int32, Int64, Object, SByte, Single, String, Time, UInt16, UInt32, UInt64, VarNumeric, AnsiStringFixedLength, StringFixedLength, Xml, DateTime2, DateTimeOffset
  $columnDefinitions += ($column.ColumnName + ' ' + $column.DataType.Name)
 }

 $sqliteCommand = $SQLiteConnection.CreateCommand()
 $sqliteCommand.CommandText = 'CREATE TABLE IF NOT EXISTS ' + $table + ' (' + [System.String]::Join(', ', $columnDefinitions) + ')'
 $rowsAffected = $sqliteCommand.ExecuteNonQuery()

 $InsertCommand = 'INSERT INTO ' + $table + ' (' + [System.String]::Join(', ', $Data.Tables.Columns.ColumnName) + ') VALUES (:' + [System.String]::Join(', :', $Data.Tables.Columns.ColumnName) + ')'

 $sqliteDataAdapter = [System.Data.SQLite.SQLiteDataAdapter]::new($SQLiteConnection)
 $sqliteDataAdapter.MissingSchemaAction = [System.Data.MissingSchemaAction]::AddWithKey
 $sqliteDataAdapter.InsertCommand = [System.Data.SQLite.SQLiteCommand]::new($InsertCommand, $SQLiteConnection)

 foreach ($column in $Data.Tables[$table].Columns) {
  $null += $sqliteDataAdapter.InsertCommand.Parameters.Add($column.ColumnName, $column.DataType.Name, $column.MaxLength, $column.ColumnName)
 }

 $rowsAffected = $sqliteDataAdapter.Update($Data, $table)
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM