使用主键通过LINQ连接DataTable返回空表,求正确实现方案
问题描述
尝试通过主键(两张表的ID列均为主键)连接clientDT和orderDT,但查询结果为空表。以下是表结构、数据、期望结果及当前代码,请修正查询以得到正确结果。
表结构与数据
clientDT
| ID | name | city |
|---|---|---|
| 1 | John | New York |
| 2 | Jacob | Los Angeles |
| 3 | William | Chicago |
| 4 | Ethan | San Francisco |
orderDT
| ID | order_number |
|---|---|
| 1 | 123547 |
| 2 | 568688 |
| 3 | 89779 |
期望结果表
| name | order_number | city |
|---|---|---|
| John | 123547 | New York |
| Jacob | 568688 | Los Angeles |
| William | 89779 | Chicago |
当前代码
var result = from client in clientDT.AsEnumerable() join orders in orderDT.AsEnumerable() on clientDT.PrimaryKey equals orderDT.PrimaryKey select new { Name = client.Field<string>("name"), City = client.Field<string>("city"), Order_number = orders.Field<string>("order_number") }; DataTable dt = new DataTable(); dt.Columns.Add("name", typeof(string)); dt.Columns.Add("city", typeof(string)); dt.Columns.Add("order_number", typeof(string)); foreach(var row in result) { dt.Rows.Add(new object[] { row.Name, row.City, row.Order_number}); } result_DT = dt;
问题原因与修正方案
错误出在连接条件:你用了clientDT.PrimaryKey和orderDT.PrimaryKey,这两个是表的主键定义对象(DataColumn数组),并非当前行的主键值,自然无法匹配到任何数据。
基础修正代码(直接指定主键列名)
直接取每行的ID列值进行匹配,这是最直观的写法:
var result = from client in clientDT.AsEnumerable() join orders in orderDT.AsEnumerable() on client.Field<int>("ID") equals orders.Field<int>("ID") select new { Name = client.Field<string>("name"), City = client.Field<string>("city"), Order_number = orders.Field<string>("order_number") }; DataTable dt = new DataTable(); dt.Columns.Add("name", typeof(string)); dt.Columns.Add("city", typeof(string)); dt.Columns.Add("order_number", typeof(string)); foreach(var row in result) { dt.Rows.Add(new object[] { row.Name, row.City, row.Order_number}); } result_DT = dt;
动态主键匹配(无需硬编码列名)
如果想通过表的主键定义动态获取值,避免硬编码列名,可以这样写:
// 假设两张表都是单主键,取第一个主键列 var clientPkCol = clientDT.PrimaryKey[0]; var orderPkCol = orderDT.PrimaryKey[0]; var result = from client in clientDT.AsEnumerable() join orders in orderDT.AsEnumerable() on client[clientPkCol] equals orders[orderPkCol] select new { Name = client.Field<string>("name"), City = client.Field<string>("city"), Order_number = orders.Field<string>("order_number") }; // 后续创建DataTable的代码不变
额外优化建议
- 若
order_number实际存储的是整数类型,建议改用Field<int>("order_number"),避免不必要的字符串类型转换。 - 如果需要保留无订单的客户(比如示例中的Ethan),可改用左连接:
var result = from client in clientDT.AsEnumerable() join orders in orderDT.AsEnumerable() on client.Field<int>("ID") equals orders.Field<int>("ID") into orderGroup from order in orderGroup.DefaultIfEmpty() select new { Name = client.Field<string>("name"), City = client.Field<string>("city"), Order_number = order?.Field<string>("order_number") ?? string.Empty };
内容的提问来源于stack exchange,提问作者sereganator
相关产品推荐
相关产品推荐

