As I've mentioned before, of all of the areas where things have changed in .NET, ADO.NET is probably the biggest (at least it's one of the top 3). In classic ADO, there weren't DataSets , DataTables or most other ADO.NET objects. In classic ADO, if you needed to join two tables, typically you'd write the SQL statement and include the join and pull back all of the data. By very definition, you are pulling back redundant data when you use this method. This has many drawbacks to it, the most striking of which is performance - after all, it takes a lot longer to pull back Xmb of data than it does X/10mb of data. This is where ADO.NET really shines. But, if you don't join your tables and pull them into a recordset, how do you get the data back? In comes the DataRelation.
This isn't a really difficult concept, but if you aren't familiar with DataSets and DataTables, I'd suggest you read up on before continuing. To begin with, I'm going to assume that you have two tables, Transactions and TransactionDetails. They have a bunch of fields in them, but they are related by a common field, TransactionID. So, the first thing you'd do is pull back all of the relevant data from both tables:
| DataSet ds = new DataSet(); SqlConnection cn = new SqlConnection(ConfigurationSettings.AppSettings("ConnectString")); SqlCommand cmd = new SqlCommand("usp_FillTransactions", cn); cmd.CommandType = CommandType.StoredProcedure; SqlDataAdapter daTransactions = new SqlDataAdapter(cmd); daTransactions.Fill(ds, "Transactions"); //pass in ds as DataSet, and "Transactions" as the table name SqlCommand cmdDetails = new SqlCommand("usp_FillTransactionDetails", cn); cmd.CommandType = CommandType.StoredProcedure; SqlDataAdapter daTransactionDetails = new SqlDataAdapter(cmdDetails); daTransactionDetails.Fill(ds, "Details"); |
| VB.NET: 'For simple single column relation Dim Tran_Detail as New DataRelation("ds", ds.Tables(0).Columns("TransID"), ds.Tables(1).Columns("TransID")) You can also use all Ordinal references or mix them as you see fit. Assuming that TransID was the first column in both Datatables, the following would work the same: Dim Tran_Detail as New DataRelation("MyRelationName", ds.Tables("Transactions").Columns(0), ds.Tables("Details").Columns(0)) 'or Dim Tran_Detail as New DataRelation("MyRelationName", ds.Tables(0).Columns(0), ds.Tables(1).Columns(0)) 'Finally ds.Relations.Add(Tran_Detail) |
| C# DataRelation Tran_Detail = new DataRelation("ds", ds.Tables[0].Columns["TransID"], ds.Tables[1].Columns["TransID"]); //For the sake of brevity I'm not going to translate each of the above, but you can switch between the nominal or the ordinal and provided //you use the correct index, it will work the same ds.Relations.Add(Tran_Detail); Like I said, this is the simplest of the constructors. The other overloads are provided below: DataRelation(string, ParentDataColum(), ChildDataColumn()) 'this takes an array of DataColumns, so you could use this constructor the same way we did above DataRelation(string, ParentDataColumn, ChildDataColumn, Boolean) //Where the boolean instructs the DataRelation whether or not to enforce //the constraints. For good reason Constraints are enabled by default, and I'd recommend against setting this to false unless you have a //really good reason to do so...and if you do, don't complain to me when a user does something you didn't intend and your validation code //misses it. //Similarly, there is an Array Based constructor with the Boolean: DataRelations(string, ParentDataColumn(), ChildDataColumn(), Boolean) //this is identical to the one above it except it allows the use of multiple columns aka Composite Keys The final constructor allows you to simply name the tables and the columns, but this will already be done most of the time. For that reason, I'm not going to address, but it's Here if you find the need to use it. |
| VB.NET 'Declare the Columns - even though we have multiple fields, we only have two tables, hence TransactionColumns and DetailColumns Dim TransactionColumns() as DataColumn Dim DetailColumns() as DataColumn TransactionColumns = New DataColum(){ds.Tables(0).Columns("TransID"), ds.Tables(0).Columns("CustomerID"), ds.Tables(0).Columns("SalePersonID")} DetailColumns = New DataColumns(){ds.Tables(1).Columns("TransID"), ds.Tables(1).Columns("CustomerID"), ds.Tables(1).Columns("SalesPersonID")} 'We could also use all norminals, ordinals or any mixture of them 'Add the name and DataColumn arrays to the Relation Dim Tran_Detail as New DataRelation("myRelationName", TransActionColumns, DetailColumns) 'Add the Relation to the DataSet ds.Relations.Add(Tran_Detail) |
| C# DataColumn[] TransactionColumns; DataColumn[] DetailColumns; TransactionColumns = new DataColumn[] {ds.Tables[0].Columns["TransID"], ds.Table[0].Columns["CustomerID"], ds.Tables[0].Columns["SalePersonID"]}; DetailColumns = new DataColumn[] {ds.Tables[1].Columns["TransID"], ds.Table[1].Columns["CustomerID"], ds.Tables[1].Columns["SalePersonID"]}; DataRelation Tran_Detail = new DataRelation("myDataRelation", TransactionColumns, DetailColumns); ds.Relations.Add(Tran_Detail); |
| VB.NET Dim Tran_Detail as New DataRelation("myRelationName", TransActionColumns, DetailColumns, True) |
| C# DataRelation Tran_Detail = new DataRelation("myDataRelation", TransactionColumns, DetailColumns, true); |