byrmol Blog

Garbage

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....