11-4. Call another model definition function in the model definition function
Problem
Want to use a "model definition" function to implement another "model definition" function
Solution Solutions
Let's say we already have a corporate partnership together with their structural model, as Figure 11-4 shows:
Figure 11-4. a model representing the associate types in A company together with the reporting association
In our virtual company, team members are managed by a team leader. Team leaders is managed by project managers. Instead, supervisors manages project managers.
If we want to return all team members that they manage from a given project manager or supervisor, we will need to get to team members through project managers and team leaders. To hide the complexity of navigating through these layers, we can create a "model definition" function to access these navigation properties more simply and directly:
1. In Solution resource management, right-click the. edmx file, open with? XML Editor.
2. Insert the code in Listing 11-7 into the <Schema> tab of the concept layer, so that the function is defined
Listing 11-7. model-defined Functions for Navigating the Associate Hierarchy
<function name= "Getprojectmanager" returntype= "Efrecipesmodel1104.projectmanager" >
<parameter name= "Teammember" type= "Efrecipesmodel1104.teammember"/>
<DefiningExpression>
Treat (Teammember. Manager.manager as Efrecipesmodel1104.projectmanager)
</DefiningExpression>
</Function>
<function name= "Getsupervisor" returntype= "Efrecipesmodel1104.supervisor" >
<parameter name= "Teammember" type= "Efrecipesmodel1104.teammember"/>
<DefiningExpression>
Treat (Efrecipesmodel1104.getprojectmanager (teammember). Manager as
Efrecipesmodel1104.supervisor)
</DefiningExpression>
</Function>
3. Insert and query the code for the model, as shown in Listing 11-8:
Listing 11-8. Using Both ESQL and LINQ to Query the Model
Class Program
{
static void Main (string[] args)
{
Runexample ();
Console.WriteLine ("\npress any key to exit ...");
Console.readkey ();
}
static void Runexample ()
{
using (var context = new EFRecipesEntities1104 ())
{
Context. Database.executesqlcommand ("Delete from Chapter11.associate");
var john = new Supervisor {Name = "john Smith"};
var Steve = new Supervisor {Name = "Steve Johnson"};
var jill = new Projectmanager
{
Name = "Jill Masterson",
Manager = John
};
var karen = new Projectmanager
{
Name = "Karen carns",
Manager = Steve
};
var bob = new Teamlead {Name = "Bob Richardson", Manager = Karen};
var tom = new Teamlead {Name = "Tom Landers", Manager = Jill};
var nancy = new Teammember {Name = "Nancy Jones", Manager = Tom};
var stacy = new Teammember
{
Name = "Stacy Rutgers",
Manager = Bob
};
Context. Associates.add (John);
Context. Associates.add (Steve);
Context. SaveChanges ();
}
using (var context = new EFRecipesEntities1104 ())
{
Console.WriteLine ("Using ESQL ...");
var emps = context. Associates.oftype<teammember> ()
This where is the source of the download of the form, but it is not how to see the ESQL
. Where (q = q.manager.name = = "Jill Masterson" | | q.manager.name = = "Steve Johnson");
This is where the code in the book, like ESQL, but can not find where this form of overloading, may be in an extension package, have knowledge, hope enlighten!
// . Where (@ "Efrecipesmodel1104.getprojectmanager (IT). Name = @projectManager | |
Efrecipesmodel.getsupervisor (IT). Name = = @supervisor ",
New ObjectParameter ("Projectmanager", "Jill Masterson"),
New ObjectParameter ("Supervisor", "Steve Johnson");
Console.WriteLine ("Team members", "Report up to either");
Console.WriteLine ("Project Manager Jill Masterson");
Console.WriteLine ("or Supervisor Steve Johnson");
foreach (var emp in emps)
{
Console.WriteLine ("\tassociate: {0}", emp. Name);
}
}
using (var context = new EFRecipesEntities1104 ())
{
Console.WriteLine ();
Console.WriteLine ("Using LINQ ...");
var emps = from E in context. Associates.oftype<teammember> ()
where Myfunctions.getprojectmanager (e). Name = =
"Jill Masterson" | |
Myfunctions.getsupervisor (E). Name = = "Steve Johnson"
Select E;
Console.WriteLine ("Team members", "Report up to either");
Console.WriteLine ("Project Manager Jill Masterson");
Console.WriteLine ("or Supervisor Steve Johnson");
foreach (var emp in emps)
{
Console.WriteLine ("\tassociate: {0}", emp. Name);
}
}
}
}
public class Myfunctions
{
[Edmfunction ("EFRecipesModel1104", "Getprojectmanager")]
public static Projectmanager Getprojectmanager (Teammember member)
{
throw new NotSupportedException ("Direct calls not supported.");
}
[Edmfunction ("EFRecipesModel1104", "Getsupervisor")]
public static Supervisor Getsupervisor (Teammember member)
{
throw new NotSupportedException ("Direct calls not supported.");
}
}
The above listing 11-8 code output is as follows:
Using ESQL ...
Team members this report up to either
Project Manager Jill Masterson
or Supervisor Steve Johnson
Associate:nancy Jones
Associate:stacy Rutgers
Using LINQ ...
Team members this report up to either
Project Manager Jill Masterson
or Supervisor Steve Johnson
Associate:nancy Jones
Associate:stacy Rutgers
How does it work?
In the Getsupervisor () function as shown in listing 11-7, we need to do three navigation for the Manager attribute. The first time from Teammember to Teamlead, the second time from Teamlead, Navigate to Projectmanager, and the last time you navigate from Projectmanager to supervisor. In Listing 11-7, we also define the Getprojectmanager () function, so we can use this function to simplify the getsupervisor () function.
We use the treat () operator of ESQL to convert a company partner instance into their correct type (Projectmanager or supervisor). If you do not use this operator, EF throws an exception (you cannot encounter mapping associate to Projectmanager or supervisor)
In Listing 11-8, using the Getprojectmanager () and Getsupervisor () functions, we can make our code simple because it hides all the details of traversing the object graph through the manager navigation property.
Because our function does not return a iqueryable<t>, we do not have to implement run-time Methods for LINQ queries, only to use their method stubs.
Attached: Creating a script file for the database used by the sample
Entity Framework 6 Recipes 2nd Edition (11-4)---Call another model definition function in the model definition function