【发布时间】: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