如何将 SQL 查询应用于 C# DataTable/Dataset?

新手上路,请多包涵

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

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

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

原文由 Eternal21 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1k
2 个回答

如果您的用户将输入除了最简单的选择语句之外的任何内容,那么您将很难做到这一点。我想为您的项目编写一个完整的 SQL 解析器会非常昂贵,但这基本上就是您所说的。

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

可能的解决方案

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

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

我自己没有使用过 Linqer。

其他一些想法

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

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

原文由 Tim Lehner 发布,翻译遵循 CC BY-SA 3.0 许可协议

这对我将 DataSet 导出到 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)
}

原文由 Rune 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进