DataTable Relational Operators in C# - JOIN Method
This JOIN method is equivalent to the TSQL INNER JOIN expression using equality.
This method returns all columns from both tables.
Once again, column name collision is avoided by appending "_Second" to the columns affected.
There are a total of 3 signatures for this method.
In summary the code works as follows:
Create new empty table
Create a DataSet and add tables.
Get a reference to Join columns
Create a DataRelation
Construct JOIN table columns
Using the DataRelation add rows with matching related rows using array manipulation
Return table
//FJC = First Join Column
//SJC = Second Join Column
public static DataTable Join (DataTable First, DataTable Second, DataColumn[] FJC, DataColumn[] SJC)
{
//Create Empty Table
DataTable table = new DataTable("Join");
// Use a DataSet to leverage DataRelation
using(DataSet ds = new DataSet())
{
//Add Copy of Tables
ds.Tables.AddRange(new DataTable[]{First.Copy(),Second.Copy()});
//Identify Joining Columns from First
DataColumn[] parentcolumns = new DataColumn[FJC.Length];
for(int i = 0; i < parentcolumns.Length; i++)
{
parentcolumns[i] = ds.Tables[0].Columns[FJC[i].ColumnName];
}
//Identify Joining Columns from Second
DataColumn[] childcolumns = new DataColumn[SJC.Length];
for(int i = 0; i < childcolumns.Length; i++)
{
childcolumns[i] = ds.Tables[1].Columns[SJC[i].ColumnName];
}
//Create DataRelation
DataRelation r = new DataRelation(string.Empty,parentcolumns,childcolumns,false);
ds.Relations.Add(r);
//Create Columns for JOIN table
for(int i = 0; i < First.Columns.Count; i++)
{
table.Columns.Add(First.Columns[i].ColumnName, First.Columns[i].DataType);
}
for(int i = 0; i < Second.Columns.Count; i++)
{
//Beware Duplicates
if(!table.Columns.Contains(Second.Columns[i].ColumnName))
table.Columns.Add(Second.Columns[i].ColumnName, Second.Columns[i].DataType);
else
table.Columns.Add(Second.Columns[i].ColumnName + "_Second", Second.Columns[i].DataType);
}
//Loop through First table
table.BeginLoadData();
foreach(DataRow firstrow in ds.Tables[0].Rows)
{
//Get "joined" rows
DataRow[] childrows = firstrow.GetChildRows(r);
if(childrows != null && childrows.Length > 0)
{
object[] parentarray = firstrow.ItemArray;
foreach(DataRow secondrow in childrows)
{
object[] secondarray = secondrow.ItemArray;
object[] joinarray = new object[parentarray.Length+secondarray.Length];
Array.Copy(parentarray,0,joinarray,0,parentarray.Length);
Array.Copy(secondarray,0,joinarray,parentarray.Length,secondarray.Length);
table.LoadDataRow(joinarray,true);
}
}
}
table.EndLoadData();
}
return table;
}
public static DataTable Join (DataTable First, DataTable Second, DataColumn FJC, DataColumn SJC)
{
return SQLOps.Join(First, Second, new DataColumn[]{FJC}, new DataColumn[]{SJC});
}
public static DataTable Join (DataTable First, DataTable Second, string FJC, string SJC)
{
return SQLOps.Join(First, Second, new DataColumn[]{First.Columns[FJC]}, new DataColumn[]{First.Columns[SJC]});
}
Legacy Comments
ELmO
2004-01-28 |
re: DataTable Relational Operators in C# - JOIN Method Interesting. |
Ben
2004-04-13 |
re: DataTable Relational Operators in C# - JOIN Method Very neat code, I'm using this to join two DataSets from completely different sources (MS SQL Server and a Windows Indexing Service) and it works exactly as expected. Thanks David |
Jeff
2004-07-10 |
re: DataTable Relational Operators in C# - JOIN Method Here is VB version. Sorry, have to follow company's standards. Public Shared Function Join(ByVal first As DataTable, ByVal second As DataTable, ByVal firstJoinColumn As DataColumn, ByVal secondJoinColumn As DataColumn) As DataTable Return Join(first, second, New DataColumn() {firstJoinColumn}, New DataColumn() {secondJoinColumn}) End Function Public Shared Function Join(ByVal first As DataTable, ByVal second As DataTable, ByVal firstJoinColumn As String, ByVal secondJoinColumn As String) As DataTable Return Join(first, second, New DataColumn() {first.Columns(firstJoinColumn)}, New DataColumn() {second.Columns(secondJoinColumn)}) End Function Public Shared Function Join(ByVal first As DataTable, ByVal second As DataTable, ByVal firstJoinColumns As DataColumn(), ByVal secondJoinColumns As DataColumn()) As DataTable ' Create Empty Table Dim oTable As DataTable = New DataTable("Join") ' Use a DataSet to leverage DataRelation Dim oDataSet As DataSet = New DataSet With oDataSet ' Add Copy of Tables .Tables.AddRange(New DataTable() {first.Copy, second.Copy}) ' Identify Joining Columns from First Dim arrParentColumns(firstJoinColumns.Length - 1) As DataColumn For iCounter As Int32 = 0 To arrParentColumns.Length - 1 arrParentColumns(iCounter) = oDataSet.Tables(0).Columns(firstJoinColumns(iCounter).ColumnName) Next ' Identify Joining Columns from Second Dim arrChildColumns(secondJoinColumns.Length - 1) As DataColumn For iCounter As Int32 = 0 To arrChildColumns.Length - 1 arrChildColumns(iCounter) = oDataSet.Tables(1).Columns(secondJoinColumns(iCounter).ColumnName) Next ' Create DataRelation Dim oDataRelation As DataRelation = New DataRelation(String.Empty, arrParentColumns, arrChildColumns, False) .Relations.Add(oDataRelation) ' Create Columns for JOIN table For iCounter As Int32 = 0 To first.Columns.Count - 1 oTable.Columns.Add(first.Columns(iCounter).ColumnName, first.Columns(iCounter).DataType) Next For iCounter As Int32 = 0 To second.Columns.Count - 1 ' Beware Duplicates If Not oTable.Columns.Contains(second.Columns(iCounter).ColumnName) Then oTable.Columns.Add(second.Columns(iCounter).ColumnName, second.Columns(iCounter).DataType) Else oTable.Columns.Add(second.Columns(iCounter).ColumnName & "_Second", second.Columns(iCounter).DataType) End If Next ' Loop through First table oTable.BeginLoadData() For Each oFirstTableDataRow As DataRow In oDataSet.Tables(0).Rows ' Get "joined" rows Dim childRows As DataRow() = oFirstTableDataRow.GetChildRows(oDataRelation) If Not childRows Is Nothing AndAlso childRows.Length > 0 Then Dim arrParentArray() As Object = oFirstTableDataRow.ItemArray For Each oSecondTableDataRow As DataRow In childRows Dim arrSecondArray() As Object = oSecondTableDataRow.ItemArray Dim arrJoinArray(arrParentArray.Length + arrSecondArray.Length - 1) As Object Array.Copy(arrParentArray, 0, arrJoinArray, 0, arrParentArray.Length) Array.Copy(arrSecondArray, 0, arrJoinArray, arrParentArray.Length, arrSecondArray.Length - 1) oTable.LoadDataRow(arrJoinArray, True) Next End If Next oTable.EndLoadData() End With Return oTable End Function |
Jeff
2004-07-10 |
re: DataTable Relational Operators in C# - JOIN Method Sorry, found a bug. Array.Copy(arrSecondArray, 0, arrJoinArray, arrParentArray.Length, arrSecondArray.Length -1) Should be Array.Copy(arrSecondArray, 0, arrJoinArray, arrParentArray.Length, arrSecondArray.Length) |
Kirk Kennison
2004-08-04 |
re: DataTable Relational Operators in C# - JOIN Method Here is a left outer join, based on the above c# code: using System; using System.Data; namespace MyNameSpace { /// <summary> /// Summary description for SQLOps. /// </summary> public class SQLOps { public SQLOps() { } //FJC = First Join Column //SJC = Second Join Column public static DataTable Join (DataTable First, DataTable Second, DataColumn[] FJC, DataColumn[] SJC) { //Create Empty Table DataTable table = new DataTable("Join"); // Use a DataSet to leverage DataRelation using(DataSet ds = new DataSet()) { //Add Copy of Tables ds.Tables.AddRange(new DataTable[]{First.Copy(),Second.Copy()}); //Identify Joining Columns from First DataColumn[] parentcolumns = new DataColumn[FJC.Length]; for(int i = 0; i < parentcolumns.Length; i++) { parentcolumns[i] = ds.Tables[0].Columns[FJC[i].ColumnName]; } //Identify Joining Columns from Second DataColumn[] childcolumns = new DataColumn[SJC.Length]; for(int i = 0; i < childcolumns.Length; i++) { childcolumns[i] = ds.Tables[1].Columns[SJC[i].ColumnName]; } //Create DataRelation DataRelation r = new DataRelation(string.Empty,parentcolumns,childcolumns,false); ds.Relations.Add(r); //Create Columns for JOIN table for(int i = 0; i < First.Columns.Count; i++) { table.Columns.Add(First.Columns[i].ColumnName, First.Columns[i].DataType); } for(int i = 0; i < Second.Columns.Count; i++) { //Beware Duplicates if(!table.Columns.Contains(Second.Columns[i].ColumnName)) table.Columns.Add(Second.Columns[i].ColumnName, Second.Columns[i].DataType); else table.Columns.Add(Second.Columns[i].ColumnName + "_Second", Second.Columns[i].DataType); } //Loop through First table table.BeginLoadData(); foreach(DataRow firstrow in ds.Tables[0].Rows) { //Get "joined" rows DataRow[] childrows = firstrow.GetChildRows(r); if(childrows != null && childrows.Length > 0) { object[] parentarray = firstrow.ItemArray; foreach(DataRow secondrow in childrows) { object[] secondarray = secondrow.ItemArray; object[] joinarray = new object[parentarray.Length+secondarray.Length]; Array.Copy(parentarray,0,joinarray,0,parentarray.Length); Array.Copy(secondarray,0,joinarray,parentarray.Length,secondarray.Length); table.LoadDataRow(joinarray,true); } } else { object[] parentarray = firstrow.ItemArray; object[] joinarray = new object[parentarray.Length]; Array.Copy(parentarray,0,joinarray,0,parentarray.Length); table.LoadDataRow(joinarray,true); } } table.EndLoadData(); } return table; } public static DataTable Join (DataTable First, DataTable Second, DataColumn FJC, DataColumn SJC) { return SQLOps.Join(First, Second, new DataColumn[]{FJC}, new DataColumn[]{SJC}); } public static DataTable Join (DataTable First, DataTable Second, string FJC, string SJC) { return SQLOps.Join(First, Second, new DataColumn[]{First.Columns[FJC]}, new DataColumn[]{First.Columns[SJC]}); } } } |
Keen Bean
2004-11-11 |
Works Fantasticly This works like a dream and has stream-lined my code incredibly... thanking you! |
Jitendra Singh
2005-07-25 |
re: DataTable Relational Operators in C# - JOIN Method Thanks a lot, this code is really good. |
Mike
2005-08-07 |
re: DataTable Relational Operators in C# - JOIN Method Could someone post an example of the method call. I tried passing in the column names and the column objects and it doesn't work for me. Thanks Mike |
Sam
2005-09-10 |
re: DataTable Relational Operators in C# - JOIN Method Works really well. Has saved me much time. Thank you so much. |
Ritesh Ramesh
2005-11-08 |
re: DataTable Relational Operators in C# - JOIN Method Im nottoo sure but looks like the following code public static DataTable Join (DataTable First, DataTable Second, string FJC, string SJC) { return SQLOps.Join(First, Second, new DataColumn[]{First.Columns[FJC]}, new DataColumn[]{First.Columns[SJC]}); } Should have been public static DataTable Join (DataTable First, DataTable Second, string FJC, string SJC) { return SQLOps.Join(First, Second, new DataColumn[]{First.Columns[FJC]}, new DataColumn[]{Second.Columns[SJC]}); } Most people have probably join on similar column names hence may not have realised the difference. But this is easily fixed. RR |
Chad Hughes
2005-12-03 |
re: DataTable Relational Operators in C# - JOIN Method SQLOps, Is this from a .NET class? |
Rajeev Ranjan
2006-04-22 |
re: DataTable Relational Operators in C# - JOIN Method Chad, from Kirk's example you can make out that its a user defined class. Mike, the method call would be simply something like: System.Data.DataTable table1 = new System.Data.DataTable("JoinTable1"); System.Data.DataTable table2 = new System.Data.DataTable("JoinTable2"); System.Data.DataTable dt = Join(table1,table2, "Id", "Id"); And before calling the method you'll populate the tables. ;) |
Michael Rivera
2006-06-23 |
re: DataTable Relational Operators in C# - JOIN Method Nice work. However, I am unable to get the Left Outer Join example to work. |
Michael Rivera
2006-06-23 |
re: DataTable Relational Operators in C# - JOIN Method I figured out my problem with the left outer join. It was developer error. Disregard previous message |
Ingo
2006-09-19 |
re: DataTable Relational Operators in C# - JOIN Method Thank you for the nice work. Saved me much time. |
Alan Heywood
2006-09-22 |
re: DataTable Relational Operators in C# - JOIN Method Thanks for this, what a time saver. |
iggydarsa
2007-03-08 |
re: DataTable Relational Operators in C# - JOIN Method SAVED TIME< THANKS!!! I think I found a bug tho... Instead of; public static DataTable Join (DataTable First, DataTable Second, string FJC, string SJC) { return SQLOps.Join(First, Second, new DataColumn[]{First.Columns[FJC]}, new DataColumn[]{First.Columns[SJC]}); } it should be; public static DataTable Join (DataTable First, DataTable Second, string FJC, string SJC) { return SQLOps.Join(First, Second, new DataColumn[]{First.Columns[FJC]}, new DataColumn[]{Second.Columns[SJC]}); } If I'm wrong please let me know. |
Steve Stokes
2007-06-08 |
re: DataTable Relational Operators in C# - JOIN Method Thank you SO MUCH for this code, it has helped us EMMENSLY!!! You saved my job dude! thanks!!!!!!! |
Kris
2007-06-29 |
re: DataTable Relational Operators in C# - JOIN Method Worked great for my needs...I had to add support for deleted rows, the code will try to put them in the resulting join. I just checked for row state = deleted after this statement and again for the child rows: DataRow[] childrows = firstrow.GetChildRows(r); Thanks! |
Yibing
2007-07-07 |
re: DataTable Relational Operators in C# - JOIN Method This is very nice and exactly what I want to do. However, I got an error on the following line: //Create DataRelation DataRelation r = new DataRelation(string.Empty,parentcolumns,childcolumns,false); ds.Relations.Add(r); complaining about the column types are different between parentcolumns and childcolumns. Basically I loaded one Datatable for SQL server and another one from Oracle. One in SQL is using "int" and one in Oracle is using "Number". How could I improve it so that this program can run as long as the values match? Thanks! Yibing |
Raman Sachin Omar
2007-09-14 |
re: DataTable Relational Operators in C# - JOIN Method Very Fine Job.It's was very time saving for me |
Sergey Radkevich
2007-10-25 |
There is an article in MSDN http://support.microsoft.com/kb/326080 |
Tigris
2008-01-18 |
re: DataTable Relational Operators in C# - JOIN Method Yes iggydarsa, I agree with you... that is a bug. I know this post is kind of aged, but I only found it yesterday and it is very helpful to me. Thank you!! |
Pal
2008-02-18 |
re: DataTable Relational Operators in C# - JOIN Method Hey David/Kirk: Thanks a BIG BUNCH for the c# equivalent for the Left join in C#. It worked like a charm!!!!!!!!!!!!!! This saved me tons and tons of work and pain. If not for this code, I would have been going around and around and wasting time. Thanks again!!! -Pal |
Harris
2008-03-12 |
re: DataTable Relational Operators in C# - JOIN Method What would the full outer join look like. I am having trouble converting it. Thanks. |
Pablo Alejandro Pérez Acosta
2008-05-09 |
re: DataTable Relational Operators in C# - JOIN Method Very Thanks for your code, It worked smoothly on my app... |
pako
2008-09-25 |
re: DataTable Relational Operators in C# - JOIN Method thx man |
Sergey D
2008-11-20 |
re: DataTable Relational Operators in C# - JOIN Method It works great. Thank you. Just one thing. I'm using Russian locale, so temporary DataSet: using(DataSet ds = new DataSet()) is created with locale ru-Ru. Due to this, relation r couldn't be added. So I had to set locale as English manually. After that all worked fine. |
Amar
2009-01-30 |
re: DataTable Relational Operators in C# - JOIN Method Thanks for the listing. Works fine for my requirement. |
Maw
2009-03-09 |
re: DataTable Relational Operators in C# - JOIN Method Hi I know how to join two tables using one field. Dim dtJoin As DataTable = _Join.Join(dt1, dt2, "id", "id") What about if you want to join based on 2 or 3 fields. e.g select * from tbl1 INNER JOIN tbl2 ON tbl1.id=tbl2.id and tbl1.fname=tbl2.fname and tbl1.lname = tbl2.lname? Lastly how do you use datacolumn paramater in the code? Thank you. |
Quinton
2009-06-18 |
re: DataTable Relational Operators in C# - JOIN Method Hi - Great piece of code - thank you so much! One small request - Please can you provide me with code (VB) for a LEFT JOIN, if possible. Thank you. |
Manduca
2009-08-25 |
re: DataTable Relational Operators in C# - JOIN Method There is also a kb artcile from MS on HOW TO: Implement a DataSet JOIN helper class http://support.microsoft.com/kb/326080/en-us I use this helper class and it works quite good for me. |
Indika
2009-08-27 |
re: DataTable Relational Operators in C# - JOIN Method Please tell me how can i find the class "SQLOps"........... Need your help.... |
Pablo
2009-11-25 |
re: DataTable Relational Operators in C# - JOIN Method The same question, there is an object called "SQLOps", what type is that instance? or is this the Namespace? bye.. excelent work... |
Vincent Rainardi
2009-12-24 |
re: DataTable Relational Operators in C# - JOIN Method wow great piece of code. Works like a charm. Thank you David. |
john
2010-02-14 |
re: DataTable Relational Operators in C# - JOIN Method Hi.. Code's very good..I need help to execute ths..Wat's that SQLOps?..how to resolve that in my code.. |
shoobie
2010-05-19 |
re: DataTable Relational Operators in C# - JOIN Method Kirk, this was a frickin life saver! ^SQLOps is what he is calling his class.... |