【问题标题】:Produce Insert SQL queries from a Dictionary using LINQ expressions使用 LINQ 表达式从字典中生成插入 SQL 查询
【发布时间】:2015-04-27 11:48:36
【问题描述】:

如果问题具有误导性,我深表歉意,但我会尽力解释我想要实现的目标。

我有一本包含以下值的字典

Dim myDictionary As New Dictionary(Of Integer, Integer)
myDictionary.Add(1, 100)
myDictionary.Add(2, 200)
myDictionary.Add(3, 300)
myDictionary.Add(4, 400)
myDictionary.Add(5, 500)
myDictionary.Add(6, 600)

我通过循环遍历字典来生成一些插入查询,如下所示:

Dim s As String = String.Empty
For Each kvp As KeyValuePair(Of Integer, Integer)
    s &= "INSERT INTO myTable(id, qty) SELECT " & kvp.key & "," & kvp.value & ";" & vbCrLf
Next

Console.Write(s)

保存到我的 String 变量中的值如下:

INSERT INTO myTable(id, qty) SELECT 1, 100;
INSERT INTO myTable(id, qty) SELECT 2, 200;
INSERT INTO myTable(id, qty) SELECT 3, 300;
INSERT INTO myTable(id, qty) SELECT 4, 400;
INSERT INTO myTable(id, qty) SELECT 5, 500;
INSERT INTO myTable(id, qty) SELECT 6, 600;

然后,我将这些值插入到数据库中,如下所示:

myDb.ExecuteSQL(s)

我对上述内容很满意,但想探索/学习新的方法。因此,我想知道是否有办法使用LINQ 表达式生成上述输出? 例如:将INSERT 查询保存到List(of String) 的表达式

Dim myList As New String(of String)
myList = <LINQ expression here>

所以,我可以使用以下内容在控制台上打印并插入到我的数据库中。

console.Write(String.Join(vbCrLf, myList.ToString()))
myDb.ExecuteSQL(String.Join(vbCrLf, myList.ToString()))

编辑: 我知道parameterized SQL 的用法、SQL Injection 等,我一直在我的项目中使用它们。上面的例子只是为了让事情变得简单并解释我想要实现的目标。 我很想知道是否有办法通过LINQ 实现相同的效果(不一定需要更清洁),谢谢。

【问题讨论】:

  • 我想说首先要了解的是使用参数化 SQL,而不是直接在 SQL 中包含值。
  • 我同意@JonSkeet。对于 ADO.NET,您可以使用 DataAdapterDataSet,使用 InsertCommand。这将更加结构化、参数化和错误安全。
  • @SamMakin 哎呀,已修复 :)
  • @user3021830 除非您要维护遗留代码,否则请避免使用DataSetDataAdapter,否则只需添加大量数据移动和对更多设计人员的依赖,而没有任何实际好处。如果您想要这种功能,请使用 ORM。但是,在这两种情况下,您都应该知道如何使用连接、命令和数据读取器,因为当您使用更高级别的工具调试问题时,您需要知道它们在做什么。
  • Dim commands = myDictionary.Select(Function(x) new string("INSERT INTO myTable(id, qty) SELECT " &amp; x.Key &amp; "," &amp; x.Value &amp; ";")) 但实际上这并不比您当前的代码更好可读性差。

标签: c# vb.net linq linq-to-sql sql-server-2012


【解决方案1】:

f 有没有办法使用 LINQ 表达式产生上述输出?

是的,但不一定更干净。

类似的东西,在 C# 中(因为 VB lambda 看起来很糟糕)

// Get IEnum<string>, one SQL command per string
// NB. enumerating a dictionary gives IEnum<KeyValuePair<TKey, TVal>>
var exprs = myDictionary.Select(kv =>
                // Build SQL
            );

var cmdStr = String.Join("\r\n", exprs);

然而这是不好。您应该使用参数将值传递给数据库,以帮助避免 SQL 注入漏洞。

使用循环更容易:

var params = new List<DbParameter>();
int nParam = 0;
var sb = new StringBuider();

foreach (var kv in myDictionary) {
  sb.AppendFormat("INSERT INTO myTable(id, qty) values (@p{0}, @p{1})",
                  nParam, nParam+1);
  sb.AppendLine();
  params.Add(MakeDbParam("@p" + nParam.ToString(), kv.Key);
  params.Add(MakeDbParam("@p" + (nParam+1).ToString(), kv.Value);
  nParam +=2
}

然后在执行命令时包含参数集合。

【讨论】:

  • 我同意你的 cmets 并且我一直在我的项目中使用参数化 SQL。上面的例子只是为了让事情变得简单并解释我想要实现的目标。我很想知道是否有办法通过LINQ 实现相同的效果(它不一定需要更清洁)。感谢您的 cmets,非常有用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-03
相关资源
最近更新 更多