随笔 - 432  文章 - 0  评论 - 15  阅读 - 63万

C#代码中实现两个表(DataTable)的关联查询(JOIN)

之前通常都是使用SQL直接从数据库中取出表1和表2关联查询后的数据,只需要用一个JOIN就可以了,非常方便。近日遇到一种情况,两个表中的数据已经取到代码中,需要在代码中将这两个表关联起来,并得到它们横向拼在一起之后的完整数据。

如:表1--商品信息表(dtHead),存放商品的ID和名称,表结构和数据如下:

 

 

 

     表2--商品数量及金额表(dtTail),存放商品的数量、金额,表结构和数据如下:

现在要得到表1和表2横向拼接起来的表(DtAll),结果如下:

 

在C#代码中,要将这两个表拼接起来,有很多笨办法,例如循环获取数据一条条拼起来,但在数据量大的情况下会影响性能,在字段多的时候也需要写一大堆给每个字段依次赋值的代码。

使用LINQ可以帮助解决这一问题。下面提供了两种方案:

方案一:当能够确定DtAll表的字段,并且字段不是很多的情况下,可以显式写出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var query1 =
     from rHead in dtHead.AsEnumerable()
     from rTail in dtTail.AsEnumerable()
     where rHead.Field<Int32>("GoodID") == rTail.Field<Int32>("GoodID")
     select new
     {
         GoodID = rHead.Field<Int32>("GoodID"),
         GoodName = rHead.Field<String>("GoodName"),
         Num = rTail.Field<Int32>("Num"),
         Money = rTail.Field<Int32>("Money")
     };
 
 DataTable dtNew = DtAll.Copy();
 foreach (var obj in query1)
 {
     dtNew.Rows.Add(obj.GoodID, obj.GoodName, obj.Num, obj.Money);
 }

  

其中DtAll的表结构已经事先创建好了,在下面会给出所有代码。

 

方案二:LINQ提供了与SQL中类似的JOIN方法。并且当字段很多的情况下,每一个字段都在select new中写出来比较麻烦,可以使用如下的方式:

1
2
3
4
5
6
7
8
9
10
11
12
var query =
    from rHead in dtHead.AsEnumerable()
    join rTail in dtTail.AsEnumerable()
    on rHead.Field<Int32>("GoodID") equals rTail.Field<Int32>("GoodID")
    select rHead.ItemArray.Concat(rTail.ItemArray.Skip(1));
 
foreach (var obj in query)
{
    DataRow dr = DtAll.NewRow();
    dr.ItemArray = obj.ToArray();
    DtAll.Rows.Add(dr);
}

  

使用Concat将表1和表2的字段拼接起来,作为总表DtAll的字段,但由于表1、表2中都存在字段GoodID,不能在表中出现重复的字段,因此使用Skip(1)跳过表2中的第一个字段GoodID。

 

下面给出这个小例子完整的代码(不包括窗体,窗体上很简单,只有一个按钮)

首先写入测试数据:把表1、表2创建起来并插入如上图所示的数据(实际情况是表1、表2通过其他渠道直接获取到代码中的)

然后在单击“连接”按钮时,得到表1、表2横向连接后的表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Data;
 
namespace WpfApplication1
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        DataTable dtHead = new DataTable();
        DataTable dtTail = new DataTable();
        DataTable DtAll = new DataTable();
 
        public MainWindow()
        {
            InitializeComponent();
 
            this.AddData();
        }
 
        /// <summary>
        /// 创建表结构,添加数据源
        /// </summary>
        private void AddData()
        {
            dtHead.Columns.Add("GoodID", typeof(Int32));
            dtHead.Columns.Add("GoodName", typeof(String));
 
            dtTail.Columns.Add("GoodID", typeof(Int32));
            dtTail.Columns.Add("Num", typeof(Int32));
            dtTail.Columns.Add("Money", typeof(Int32));
 
            DtAll.Columns.Add("GoodID", typeof(Int32));
            DtAll.Columns.Add("GoodName", typeof(String));
            DtAll.Columns.Add("Num", typeof(Int32));
            DtAll.Columns.Add("Money", typeof(Int32));
 
            this.AddRow(1, "青岛纯生", 10, 30);
            this.AddRow(2, "哈尔滨啤酒", 5, 20);
        }
 
        /// <summary>
        /// 添加数据
        /// </summary>
        /// <param name="goodID"></param>
        /// <param name="goodName"></param>
        /// <param name="num1"></param>
        /// <param name="num2"></param>
        private void AddRow(Int32 goodID, String goodName, Int32 num1,Int32 num2)
        {
            DataRow drH = dtHead.NewRow();
            drH["GoodID"] = goodID;
            drH["GoodName"] = goodName;
            dtHead.Rows.Add(drH);
 
            DataRow drT = dtTail.NewRow();
            drT["GoodID"] = goodID;
            drT["Num"] = num1;
            drT["Money"] = num2;
            dtTail.Rows.Add(drT);
        }
 
        /// <summary>
        /// “连接”按钮单击事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_Join_Click(object sender, RoutedEventArgs e)
        {
            //方案一
            var query1 =
                from rHead in dtHead.AsEnumerable()
                from rTail in dtTail.AsEnumerable()
                where rHead.Field<Int32>("GoodID") == rTail.Field<Int32>("GoodID")
                select new
                {
                    GoodID = rHead.Field<Int32>("GoodID"),
                    GoodName = rHead.Field<String>("GoodName"),
                    Num = rTail.Field<Int32>("Num"),
                    Money = rTail.Field<Int32>("Money")
                };
 
            DataTable dtNew = DtAll.Copy();
            foreach (var obj in query1)
            {
                dtNew.Rows.Add(obj.GoodID, obj.GoodName, obj.Num, obj.Money);
            }
 
            //方案二
            var query =
                from rHead in dtHead.AsEnumerable()
                join rTail in dtTail.AsEnumerable()
                on rHead.Field<Int32>("GoodID") equals rTail.Field<Int32>("GoodID")
                select rHead.ItemArray.Concat(rTail.ItemArray.Skip(1));
 
            foreach (var obj in query)
            {
                DataRow dr = DtAll.NewRow();
                dr.ItemArray = obj.ToArray();
                DtAll.Rows.Add(dr);
            }
        }
    }
}

  

 

 

posted on   狼来了  阅读(3108)  评论(0编辑  收藏  举报
编辑推荐:
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
阅读排行:
· DeepSeek “源神”启动!「GitHub 热点速览」
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· NetPad:一个.NET开源、跨平台的C#编辑器
历史上的今天:
2015-10-11 SQL Delta实用案例介绍,很好的东西,帮了我不少忙
< 2025年2月 >
26 27 28 29 30 31 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 1
2 3 4 5 6 7 8

点击右上角即可分享
微信分享提示