【问题标题】:C# query inside a for loop returns only one valuefor 循环内的 C# 查询仅返回一个值
【发布时间】:2018-03-09 21:25:26
【问题描述】:

我正在构建一个 C# WinForms 应用程序,用户可以在该应用程序中检查随机生成的底盘编号列表是否将特定操作的底盘编号连接到零件列表,如果是,则计算可用零件编号。每个底盘编号连接到一个零件列表(或不连接)。该特定零件列表包含通过类型定义注释链接到底盘编号的零件。例如 100024 有一个类型定义注释 D13K420,因此它应该在部分列表 13080554 行中看到该类型定义注释(计数 3)。

我在 MSSQL Server 中有两个数据表。一个用于底盘号:

| ID | chassis_number | model | build_date | factory | type_defining_note | partlist |
|----|----------------|-------|------------|---------|--------------------|----------|
|  1 |         100000 |     1 | 2014-01-04 |       2 |            D13K500 | 13080553 |
|  2 |         100001 |     1 | 2014-01-06 |       2 |            D13K460 | 13080554 |
|  3 |         100002 |     1 | 2014-01-12 |       2 |            D13K460 | 13080554 |
|  4 |         100023 |     1 | 2014-01-15 |       2 |            D13K540 | 13080553 |
|  5 |         100024 |     1 | 2014-01-20 |       1 |            D13K420 | 13080554 |
|  6 |         100025 |     1 | 2014-01-26 |       2 |            D13K500 | 13080553 |
|  7 |         122312 |     1 | 2014-02-08 |       1 |            D13K500 |        0 |
|  8 |         104560 |     1 | 2014-02-09 |       1 |            D13K460 |        0 |
|  9 |         100045 |     1 | 2014-03-04 |       2 |            D13K540 |        0 |
| 10 |         100046 |     1 | 2014-03-12 |       2 |            D13K540 |        0 |

对于零件清单:

| ID | part_list_no | part_list_description | model | position | part_number | part_description | quantity | type_defining_note | action | action_type |
|----|--------------|-----------------------|-------|----------|-------------|------------------|----------|--------------------|--------|-------------|
|  1 |     13080553 |   Oil filter (Engine) |     1 |        1 |    21803087 |           Filter |        1 |            D13K500 |      1 |           P |
|  2 |     13080553 |   Oil filter (Engine) |     1 |        1 |    21803088 |           Filter |        1 |            D13K540 |      1 |           P |
|  3 |     13080553 |   Oil filter (Engine) |     1 |        2 |    24523486 |       Oil cooler |        1 |            D13K500 |      1 |           S |
|  4 |     13080553 |   Oil filter (Engine) |     1 |        2 |    24523486 |       Oil cooler |        1 |            D13K540 |      1 |           S |
|  5 |     13080553 |   Oil filter (Engine) |     1 |        3 |    27647538 |           O-ring |        2 |            D13K500 |      1 |           S |
|  6 |     13080553 |   Oil filter (Engine) |     1 |        3 |    27647538 |           O-ring |        2 |            D13K540 |      1 |           S |
|  7 |     13080553 |   Oil filter (Engine) |     1 |        4 |    23984567 |             Pipe |        1 |                    |      0 |             |
|  8 |     13080553 |   Oil filter (Engine) |     1 |        5 |    23984558 |             Pipe |        1 |                    |      0 |             |
|  9 |     13080554 |   Oil filter (Engine) |     1 |        1 |    21803085 |           Filter |        1 |            D13K420 |      1 |           P |
| 10 |     13080554 |   Oil filter (Engine) |     1 |        1 |    21803086 |           Filter |        1 |            D13K460 |      1 |           P |
| 11 |     13080554 |   Oil filter (Engine) |     1 |        2 |    24523486 |       Oil cooler |        1 |            D13K420 |      1 |           S |
| 12 |     13080554 |   Oil filter (Engine) |     1 |        2 |    24523482 |       Oil cooler |        1 |            D13K460 |      1 |           S |
| 13 |     13080554 |   Oil filter (Engine) |     1 |        3 |    27647538 |           O-ring |        2 |            D13K420 |      1 |           S |
| 14 |     13080554 |   Oil filter (Engine) |     1 |        3 |    27647538 |           O-ring |        2 |            D13K460 |      1 |           S |
| 15 |     13080554 |   Oil filter (Engine) |     1 |        4 |    23984567 |             Pipe |        1 |                    |      0 |             |
| 16 |     13080554 |   Oil filter (Engine) |     1 |        5 |    23984558 |             Pipe |        1 |                    |      0 |             |

通过简单连接建立的连接:FULL OUTER JOIN part_list ON chassis.part_list = part_list.part_list_number

我想要实现的是:

| chassis_number | parts |
|----------------|-------|
|         100000 |     3 |
|         100001 |     3 |
|         100002 |     3 |
|         100023 |     3 |
|         100024 |     3 |
|         100025 |     3 |
|         100045 |     0 |
|         100046 |     0 |
|         104560 |     0 |
|         122312 |     0 |

如果底盘号和零件列表之间存在联系,则通过类型定义注释计算所有具有有效连接的零件号,如果不是则简单地返回一个0。

我能够创建一个对零件进行计数的查询,但是将它放在 C# 中的 for 循环中仅返回一个底盘号的零件,或者如果给出了多个底盘号,则返回 0:

SELECT COUNT(chassis.chassis_number) AS parts FROM chassis FULL OUTER JOIN part_list ON chassis.part_list = part_list.part_list_number WHERE chassis.chassis_number = @chassisnumber AND part_list.action = @action AND part_list.type_defining_note LIKE(SELECT chassis.type_defining_note FROM chassis WHERE chassis.chassis_number = @chassisnumber)

以及应该返回计数部分的代码:

public static void CheckPackages()
{
    for (int i = 0; i < chassisNumber.Count; i++)
    {
        Variables.searchChassisNumber = Convert.ToInt32(chassisNumber[i]);

        try
        {
            command.Connection = connection;
            command.CommandText = "SELECT COUNT(chassis.chassis_number) AS parts FROM chassis FULL OUTER JOIN part_list ON chassis.part_list = part_list.part_list_number WHERE chassis.chassis_number = @chassisnumber AND part_list.action = @action AND part_list.type_defining_note LIKE(SELECT chassis.type_defining_note FROM chassis WHERE chassis.chassis_number = @chassisnumber)";
            command.CommandType = CommandType.Text;

            SqlParameter paramChassisNumber = new SqlParameter
            {
                ParameterName = "@chassisnumber",
                SqlDbType = SqlDbType.Int,
                Direction = ParameterDirection.Input,
                Value = Variables.searchChassisNumber
            };

            SqlParameter paramAction = new SqlParameter
            {
                ParameterName = "@action",
                SqlDbType = SqlDbType.Int,
                Direction = ParameterDirection.Input,
                Value = Variables.selectedAction
            };

            for (int j = 0; j < part.Count; j++)
            {
                part.RemoveAt(j);
            }

            command.Parameters.Add(paramChassisNumber);
            command.Parameters.Add(paramAction);

            SqlDataReader reader = command.ExecuteReader();
            while (reader.Read())
            {
                part.Add((int)reader["parts"]);
            }
            reader.Close();
            command.Parameters.Clear();

            partList.Add(new Parts(chassisNumber[i], part[i]));
        }
        catch (Exception ex)
        {
            throw new Exception(ex.Message);
        }
    }
}

我在这里阅读了其他答案,认为在循环中运行查询不太明智(性能问题,在我的情况下,我的代码中可能存在其他一些故障)。

链接到 SQLFiddle 上的示例数据库: http://sqlfiddle.com/#!6/6d4638/74

问题是:我可以使用哪些选项来获得有效的解决方案?我应该将我的查询放入 for 循环中,还是创建一个新的参数化查询,或者我应该重建整个数据库以使其正常工作?

【问题讨论】:

  • 看来您可以用part.RemoveAt(j); 替换循环,只需调用part.Clear();(不需要循环)。但这是你的意图吗?要在代码中的该点清空part 列表?
  • 我在某处看到了这种清空列表的方法。现在没关系,但是当整个事情正常时,我会清理和优化我的代码。我的问题是,当循环运行时,只执行了给定列表(chassisNumber)的第一个元素。我还需要包含 chassisNumber 列表的其他元素。

标签: c# sql-server winforms for-loop


【解决方案1】:

是的。避免在前端循环它,这对性能不利。

你几乎是在正确的轨道上。

您需要机箱 LEFT OUTER JOIN 以列出 3 个条件 partlist、type_defining_note 和 action

然后 GROUP By the chassis_number 和 couting partlist(而不是 count(*),因为您只想计算 partlist 表中存在的那些)

select chassis.chassis_number, count(partlist.part_list_no) as parts
from   chassis
       left join partlist on  chassis.partlist = partlist.part_list_no
                          and chassis.type_defining_note = partlist.type_defining_note
                          and partlist.action = '1' 
group by chassis.chassis_number

【讨论】:

  • 我尝试了您的解决方案,它在整个机箱表上运行良好,但我只需要在选定的机箱编号(for 循环中的 chassisNumber)上运行此查询,以查看这些是否有“包"(=与零件清单有联系,如果是,请计算所有符合条件的零件编号:每个底盘编号都有一个类型定义注释,零件编号也是如此,应考虑此连接)。
  • 为什么你想一次做一个,你可以一次做完
  • 我将使用您的查询来获取所有“包”,然后使用“chassisNumber”列表缩小搜索范围。谢谢!
猜你喜欢
  • 2012-11-25
  • 1970-01-01
  • 1970-01-01
  • 2019-09-20
  • 1970-01-01
  • 2021-08-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多