这个方法是从C#获取SQL值的好方法吗?

这个方法是从C#获取SQL值的好方法吗?,c#,sql-server,.net-3.5,C#,Sql Server,.net 3.5,我有一个小方法,我用它从SQL中获取东西。我用varSearch=“或varSearch=“something”来称呼它。我想知道以这种方式编写方法是最好的,还是最好将它分成两个方法(通过重载),或者我可以以某种方式将整个WHERE子句参数化 private void sqlPobierzKontrahentDaneKlienta(ListView varListView, string varSearch) { varListView.BeginUpdate();

我有一个小方法,我用它从SQL中获取东西。我用
varSearch=“
varSearch=“something”
来称呼它。我想知道以这种方式编写方法是最好的,还是最好将它分成两个方法(通过重载),或者我可以以某种方式将整个
WHERE
子句参数化

private void sqlPobierzKontrahentDaneKlienta(ListView varListView, string varSearch) {
        varListView.BeginUpdate();
        varListView.Items.Clear();
        string preparedCommand;
        if (varSearch == "") {
            preparedCommand = @"
                SELECT t1.[KlienciID],
                CASE WHEN t2.[PodmiotRodzaj] = 'Firma' THEN
                          t2.[PodmiotFirmaNazwa] ELSE 
                          t2.[PodmiotOsobaNazwisko] + ' ' + t2.[PodmiotOsobaImie] END AS 'Nazwa'
                FROM [BazaZarzadzanie].[dbo].[Klienci] t1
                INNER JOIN [BazaZarzadzanie].[dbo].[Podmioty] t2
                ON t1.[PodmiotID] = t2.[PodmiotID]
                ORDER BY t1.[KlienciID]";
        } else {
            preparedCommand = @"
                SELECT t1.[KlienciID],
                CASE WHEN t2.[PodmiotRodzaj] = 'Firma' THEN
                          t2.[PodmiotFirmaNazwa] ELSE 
                          t2.[PodmiotOsobaNazwisko] + ' ' + t2.[PodmiotOsobaImie] END AS 'Nazwa'
                FROM [BazaZarzadzanie].[dbo].[Klienci] t1
                INNER JOIN [BazaZarzadzanie].[dbo].[Podmioty] t2
                ON t1.[PodmiotID] = t2.[PodmiotID]
                WHERE t2.[PodmiotOsobaNazwisko] LIKE @searchValue OR t2.[PodmiotFirmaNazwa] LIKE @searchValue OR t2.[PodmiotOsobaImie] LIKE @searchValue
                ORDER BY t1.[KlienciID]";
        }
        using (var varConnection = Locale.sqlConnectOneTime(Locale.sqlDataConnectionDetails))
        using (SqlCommand sqlQuery = new SqlCommand(preparedCommand, varConnection)) {
            sqlQuery.Parameters.AddWithValue("@searchValue", "%" + varSearch + "%");
            using (SqlDataReader sqlQueryResult = sqlQuery.ExecuteReader())
                if (sqlQueryResult != null) {
                    while (sqlQueryResult.Read()) {
                        string varKontrahenciID = sqlQueryResult["KlienciID"].ToString();
                        string varKontrahent = sqlQueryResult["Nazwa"].ToString();
                        ListViewItem item = new ListViewItem(varKontrahenciID, 0);
                        item.SubItems.Add(varKontrahent);
                        varListView.Items.AddRange(new[] {item});
                    }
                }
        }
        varListView.EndUpdate();
    }

更好的方法实际上是使用存储过程,而不是将SQL硬编码到应用程序中。您可以将where子句参数传递给存储过程,并在数据库端处理逻辑


这种方法还提供了一个优势,即如果您在另一个应用程序(例如JAVA应用程序)中需要此逻辑,则该逻辑将集中在数据库中,因此您无需再次重写它。

我确信有更好的方法来实现此目的,例如使用存储过程,但如果确实需要这样做,则需要:

     string preparedCommandTemplate = @"
                        SELECT t1.[KlienciID],
                        CASE WHEN t2.[PodmiotRodzaj] = 'Firma' THEN
                                  t2.[PodmiotFirmaNazwa] ELSE 
                                  t2.[PodmiotOsobaNazwisko] + ' ' + t2.[PodmiotOsobaImie] END AS 'Nazwa'
                        FROM [BazaZarzadzanie].[dbo].[Klienci] t1
                        INNER JOIN [BazaZarzadzanie].[dbo].[Podmioty] t2
                        ON t1.[PodmiotID] = t2.[PodmiotID] {0}
                        ORDER BY t1.[KlienciID]";
string whereClause="WHERE t2.[PodmiotOsobaNazwisko] LIKE @searchValue OR t2.[PodmiotFirmaNazwa] LIKE @searchValue OR t2.[PodmiotOsobaImie] LIKE @searchValue"

 if (string.Emtpy.Equals(varSearch )) {
            preparedCommand = string.Format(preparedCommandTemplate,string.Empty)
        } else {
            preparedCommand = string.Format(preparedCommandTemplate,whereCaluse)

        }

如果不想使用存储过程,至少要参数化where子句。这种代码很快就会失控。我也会考虑使用免费文本索引或类似LuxeN.NET之类的方法来实现跨多个字段的“类”搜索。

在多个层次上:

  • 根本没有DAL——这意味着您的SQL代码覆盖了所有表单。糟糕的维护-至少将所有SQL处理放在一个类中

  • 这是大量手动编写的代码,因此性能很差(如:程序员性能)。查看BLToolkit,了解如何在运行时生成所有代码(从带有SQL的属性文件和抽象方法生成,带有real方法的子类是字节码生成的)

也就是说,除非我能说服您使用像NHibernate这样的真正的数据访问层/ORM

对于1,我会解雇你作为程序员(欢迎作为实习生回来)。在表单中使用SQL并不是我在重写数据库时花费时间的想法——因此,它是不可测试的,维护起来也很痛苦。这是BTW,而不是“.NET特定”——孤立SQL是我20年前(几乎)在SMALLATE和C++中所做的事情。p>
对于2,我会-好吧-由于指导原则,这不会发生;)

考虑到您希望继续在代码中使用硬编码的SQL语句(而不是切换到LINQ2SQL或Entity Framework或其他ORM工具),您肯定要做的一件事是将where子句作为参数添加到方法中(如果这就是“参数化where子句”的意思)。这使得使用此方法的客户端依赖于您的数据访问技术(在本例中为SQL数据库)

比较以下两个调用:

sqlPobierzKontrahentDaneKlienta(lv, "something");


哪一个看起来更好?

代码没有太大问题,但您是否考虑过使用LINQ2SQL或ADO.NET实体框架来实现这一点?我始终建议在代码中使用英语(我也不是英语母语),因为大多数框架都是英语的,如果您也使用英语,您的代码将集成得更好。例如,您不必考虑是使用“hinzufügen”(德语中的add)还是使用“add”,因为它是一个框架类的子类,您需要重写它。我理解这一点,通常当程序不是本地语言时,我总是使用英语。然而,在这篇文章中,将一些商业术语和名称翻译成英语对我来说毫无意义,因为我是唯一一个读、写这些术语和名称的人,而且不可能是不同的语言(波兰语)。语法可能有点不正确。我想,由于sql注入,使用字符串合并是不“允许”的,甚至是不鼓励的!除此之外,orderBy需要在WHERE之后,所以您实际上需要额外的字符串whereclause、字符串orderBy并将其合并在一起。但正如我早些时候所说,它被否决了,所以所有的:)订单将在where条款之后。{0}标记将被替换为where c lause考虑到我不是程序员而是管理员,我被赋予了一项任务,我仍然是一名实习生:-)我指的是
sqlQuery.Parameters.AddWithValue(“@whereClausule”,whereClausule)而不是方法的附加参数。但我想这是不允许的。啊,好吧。事实上,这是不允许的。请仔细阅读Frans Bouma在存储过程中的精彩日志,了解您忽略的一些非常有趣的方面。简单地说:你的方法在架构上很糟糕,你用不值得的价格购买任何(假定的)好处。你可以从头开始做这件事。是核心部分。
sqlPobierzKontrahentDaneKlienta(lv,
    "WHERE t2.[PodmiotOsobaNazwisko] LIKE '%something%' OR " +
    "      t2.[PodmiotFirmaNazwa] LIKE '%something%' OR " +
    "      t2.[PodmiotOsobaImie] LIKE '%something%'")