簡體   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