FAQ/many-to-many-database-join.md
... ...
@@ -12,7 +12,26 @@ In order to achieve the results required for this scenario, some understanding a
12 12
13 13
For this tutorial, all changes being made will exist in your CustomAdHocConfig class that is normally contained inside the Global.asax.
14 14
15
-First, we need to modify the [[InitializeReporting()|/FAQ/InitializeReporting]] method:
15
+First, we need an instance variable to hold a reference to the driver.
16
+
17
+``` csharp
18
+Public Class CustomAdHocConfig : FileSystemAdHocConfig
19
+ private oldDriver As Driver = null;
20
+
21
+ {...} 'InitializeReporting, PreExecuteReportSet, etc.
22
+End Class
23
+```
24
+
25
+``` visualbasic
26
+public class CustomAdHocConfig Inherits FileSystemAdHocConfig
27
+{
28
+ private oldDriver As Drier = Nothing
29
+
30
+ {...} //InitializeReporting, PreExecuteReportSet, etc.
31
+}
32
+```
33
+
34
+Next, we need to modify the [[InitializeReporting()|/FAQ/InitializeReporting]] method:
16 35
17 36
``` csharp
18 37
public static void InitializeReporting() {
... ...
@@ -24,6 +43,7 @@ public static void InitializeReporting() {
24 43
AdHocSettings.SqlServerConnectionString = @"INSERT_YOUR_CONNECTION_STRING_HERE";
25 44
{...}
26 45
AdHocContext.Driver.AddConstraint("[dbo].[Orders].[ShipName]", "[dbo].[Suppliers].[CompanyName]");
46
+ AdHocSettings.visibleDataSources = new string[] { "[dbo].[Orders]", "[dbo].[Suppliers]" }; //Set our visible data sources to exclude our middle table
27 47
HttpContext.Current.Session["ReportingInitialized"] = true;
28 48
}
29 49
```
... ...
@@ -42,7 +62,7 @@ Public Shared Sub InitializeReporting()
42 62
HttpContext.Current.Session("ReportingInitialized") = True
43 63
End Sub
44 64
```
45
-The statement critical to the [[InitializeReporting()|/FAQ/InitializeReporting]] method is the AddConstraint method call. Here, we set up a relationship between two columns in our two tables with a many-to-many relationship. At this point, the connector table has not entered the equation. This constraint must exist in order to select the two tables with a many-to-many relationship on the datasources tab.
65
+The statement critical to the [[InitializeReporting()|/FAQ/InitializeReporting]] method is the AddConstraint method call. Here, we set up a relationship between two columns in our two tables with a many-to-many relationship. At this point, the connector table has not entered the equation. This constraint must exist in order to select the two tables with a many-to-many relationship on the datasources tab. We will also reset the driver to re-obtain the database schema objects. This is because setting VisibleDataSources after the initialization of the current driver will not load the columns for any additional data sources.
46 66
47 67
_*NOTE:* The two columns in the fake constraint MUST have the same datatype._
48 68
... ...
@@ -51,7 +71,11 @@ Next, we modify the [[PreExecuteReportSet()|/FAQ/PreExecuteReportSet]] method.
51 71
``` csharp
52 72
public override void PreExecuteReportSet(ReportSet reportSet) {
53 73
base.PreExecuteReportSet(reportSet);
54
- AdHocContext.Driver.RemoveConstraint("[dbo].[Orders].[ShipName]", "[dbo].[Suppliers].[CompanyName]"); //temporarily remove the constraint
74
+ oldDriver = AdHocContext.Driver;
75
+ AdHocContext.Driver = new MSSQLDriver(AdHocSettings.SqlServerConnectionString); //Set the specific type of driver we were using before
76
+ AdHocSettings.VisibleDataSources = new string[] { "[dbo].[Orders]", [dbo].[Suppliers]", "[dbo].[testcon]" }; //testcon is the name of the middle table we want to join with
77
+ AdHocContext.Driver.AddConstraint("[dbo].[Orders].[OrderID]", "[dbo].[testcon].[ordernum]");
78
+ AdHocContext.Driver.AddConstraint("[dbo].[Suppliers].[SupplierID]", "[dbo].[testcon].[supplier]"); //Add the correct constraints to the driver
55 79
if(reportSet.JoinedTables.Count > 0) //check if we have selected multiple tables
56 80
{
57 81
IEnumerable<JoinedTable> jts = (from JoinedTable jt in reportSet.JoinedTables
... ...
@@ -59,7 +83,7 @@ public override void PreExecuteReportSet(ReportSet reportSet) {
59 83
(jt.RightConditionTable.Contains("Orders") || jt.RightConditionTable.Contains("Suppliers"))
60 84
select jt); //use LINQ to check if we selected the tables we want to define the relationship for
61 85
JoinedTable middleJT = new JoinedTable(){
62
- TableName = "[dbo].[testcon]" //This is our connector table
86
+ TableName = "[dbo].[testcon]"
63 87
};
64 88
if(jts.Count() == 2) //We have both tables that we want
65 89
{
... ...
@@ -67,7 +91,7 @@ public override void PreExecuteReportSet(ReportSet reportSet) {
67 91
reportSet.JoinedTables.Remove(jts.ToArray()[1]);
68 92
reportSet.JoinedTables.Remove(jts.ToArray()[0]);
69 93
//if any other joined tables exist, you can modify them according to your needs. This tutorial will not cover that scenario.
70
- reportSet.JoinedTables.Add(middleJT); //Add the connector table
94
+ reportSet.JoinedTables.Add(middleJT); //Add the connector table first. In this example, it will be the table in the FROM. Orders and Suppliers will be the JOINed tables.
71 95
reportSet.JoinedTables.Add(new JoinedTable()
72 96
{
73 97
TableName = "[dbo].[Orders]",
... ...
@@ -93,7 +117,11 @@ public override void PreExecuteReportSet(ReportSet reportSet) {
93 117
``` visualbasic
94 118
Public Overrides Sub PreExecuteReportSet(ByVal reportSet As ReportSet)
95 119
MyBase.PreExecuteReportSet(reportSet)
96
- AdHocContext.Driver.RemoveConstraint("[dbo].[Orders].[ShipName]", "[dbo].[Suppliers].[CompanyName]")
120
+ oldDriver = AdHocContext.Driver
121
+ AdHocContext.Driver = new MSSQLDriver(AdHocSettings.SqlServerConnectionString) 'Set the specific type of driver we were using before
122
+ AdHocSettings.VisibleDataSources = New string() { "[dbo].[Orders]", [dbo].[Suppliers]", "[dbo].[testcon]" } 'testcon is the name of the middle table we want to join with
123
+ AdHocContext.Driver.AddConstraint("[dbo].[Orders].[OrderID]", "[dbo].[testcon].[ordernum]")
124
+ AdHocContext.Driver.AddConstraint("[dbo].[Suppliers].[SupplierID]", "[dbo].[testcon].[supplier]") 'Add the correct constraints to the driver
97 125
If (reportSet.JoinedTables.Count > 0) Then
98 126
Dim jts As IEnumerable(Of JoinedTable) = (From jt As JoinedTable In reportSet.JoinedTables
99 127
Where (jt.DbTable.Name.Contains("Orders") OrElse jt.DbTable.Name.Contains("Suppliers")) OrElse
... ...
@@ -128,22 +156,22 @@ End Sub
128 156
129 157
The above code in the [[PreExecuteReportSet()|/FAQ/PreExecuteReportSet]] method will re-define the relationship between the two tables in a many-to-many relationship and insert the connector table silently. This will produce a working join on the two tables while leaving out the pre-defined fake join. The user will be able to freely select the two tables in the many-to-many relationship without seeing the connecting table.
130 158
131
-Finally, we need a statement in the [[PostExecuteReportSet()|/FAQ/PostExecuteReportSet]] method.
159
+Finally, we need a statement in the [[PostExecuteReportSet()|/FAQ/PostExecuteReportSet]] method to reset the driver.
132 160
133 161
``` csharp
134 162
public override void PostExecuteReportSet(ReportSet reportSet)
135 163
{
136 164
base.PostExecuteReportSet(reportSet);
137
- AdHocContext.Driver.AddConstraint("[dbo].[Orders].[ShipName]", "[dbo].[Suppliers].[CompanyName]");
165
+ AdHocContext.Driver = oldDriver;
138 166
}
139 167
```
140 168
141 169
``` visualbasic
142 170
Public Overrides Sub PostExecuteReportSet(ByVal reportSet As ReportSet)
143 171
MyBase.PostExecuteReportSet(reportSet)
144
- AdHocContext.Driver.AddConstraint("[dbo].[Orders].[ShipName]", "[dbo].[Suppliers].[CompanyName]")
172
+ AdHocContext.Driver = oldDriver
145 173
End Sub
146 174
```
147 175
148 176
149
-Re-adding the constraint after report execution will ensure that the tables will be selectable again when the user makes subsequent trips to the Report Designer. Other users in the system without the ability to select the datasources in question will not see any change in their current behavior. Report definitions using the relationship will not reflect the internal process. The fake constraint will appear in the definition.
... ...
\ No newline at end of file
0
+Resetting the driver after report execution will ensure that the tables with no relationship will be selectable again when the user makes subsequent trips to the Report Designer. Other users in the system without the ability to select the datasources in question will not see any change in their current behavior. Report definitions using the relationship will not reflect the internal process. The fake constraint will appear in the definition.
... ...
\ No newline at end of file