2-5 modeling a self-referential relationship using code first
Problem
A self-referencing table in your database, you want to use code first to model it as a person with a self-correlating entity.
Solution Solutions
Let's assume that you have a self-referencing table of 2-14 of the database diagrams shown.
Figure 2-14 a self-referencing table
Follow the steps below to model this self-referencing table and relationship:
1. Create a class Ef6recipescontext in the project that inherits from the DbContext context.
2. Create a Picturecategorypoco (Simple CLR Object) entity using code listing 2-5.
Code clearance 2-5 Create a poco entity picturecategory
1 Public classPicturecategory {2 [Key]3 [Databasegenerated (databasegeneratedoption.identity)]4 Public intCategoryId {Get;Private Set; }5 Public stringName {Get;Set; }6 Public int? Parentcategoryid {Get;Private Set; }7[ForeignKey ("Parentcategoryid")]8 PublicPicturecategory Parentcategory {Get;Set; }9 PublicList<picturecategory> subcategories {Get;Set; }Ten Publicpicturecategory () { Onesubcategories =NewList<picturecategory>(); A } -}
3. Add a Dbset<picturecategory> property in the created context object Ef6recipescontext.
4. In Ef6recipescontext, rewrite the method onmodelcreating Configure the Bidirectional Association (parentcategory and subcategories), as shown in code listing 2-6.
Proxy listing 2-6 overriding method onmodelcreating
1 Public classEf6recipescontext:dbcontext {2 PublicDbset<picturecategory> Picturecategories {Get;Set; }3 PublicEf6recipescontext ()//The original is wrong here, is written picturecontext ()4:Base("Name=ef6codefirstrecipescontext") {5 }6 protected Override voidonmodelcreating (Dbmodelbuilder modelBuilder) {7 Base. Onmodelcreating (ModelBuilder);8Modelbuilder.entity<picturecategory>()9. Hasmany (cat =Cat. Subcategories)Ten. Withoptional (cat =Cat. parentcategory); One } A}
Principle
The relationship of a database has the following characteristics: Dimension (degree), multiplicity (multiplicity), and direction (derection). A dimension refers to the number of entities (tables) in a relationship. One-and two-dimensional relationships are common. The three-and n-dimensional (n-place) relationships exist only theoretically.
Multiplicity refers to the entity type at both ends of the segment that represents the relationship (this should refer to the table, because the entity type is used in the model) quantity. You may have seen such a multiplicity of representations, 0...1 (0 or one), 1 (one) and * (many).
Finally, the direction can be bidirectional or unidirectional.
The Entity Data model supports the database relationship of the currently popular database, which is represented by a type called Association. An association type can be one-dimensional or two-dimensional, and multiplicity can be 0 ... and *, direction is two-way.
The dimension in the example is one dimension (involving only picturecategory entities), and multiplicity is 0 ... 1 and *, direction of course is bidirectional.
In the case of the example, a self-referencing table generally refers to a parent-child relationship, where each father has multiple children and a child has only one father. Because father this side of the relationship multiplicity is 0 ... 1 instead of 1. This means that for a child it may not have a father. This can be used to represent the root node. A node without a father, which is the top of the entire inheritance hierarchy.
Listing 2-7 shows a recursive enumeration of the picture directories starting from the root node. Of course, the root node is a node without a father.
1 Static voidrunexample () {2 using(varContext =NewEf6recipescontext ()) {3 varLouvre =Newpicturecategory {Name ="Louvre" };4 varChild =Newpicturecategory {Name ="Egyptian antiquites" };5 Louvre. Subcategories.add (child);6Child =Newpicturecategory {Name ="Sculptures" };7 Louvre. Subcategories.add (child);8Child =Newpicturecategory {Name ="Paintings" };9 Louvre. Subcategories.add (child);Ten varPARIS =Newpicturecategory {Name ="Paris" }; One Paris. Subcategories.add (Louvre); A varVacation =Newpicturecategory {Name ="Summer Vacation" }; - vacation. Subcategories.add (Paris); - context. Picturecategories.add (Paris); the context. SaveChanges (); - } - using(varContext =NewEf6recipescontext ()) { - varRoots = Context. Picturecategories.where (c = c.parentcategory = =NULL); +Roots. ForEach (root = Print (root,0)); - } + } A Static voidPrint (Picturecategory Cat,intLevel ) { atStringBuilder SB =NewStringBuilder (); -Console.WriteLine ("{0}{1}", SB. Append (' ', Level). ToString (), Cat. Name); -Cat. Subcategories.foreach (Child = Print (child, Level +1)); -}
The code listing 2-7 output shows that the root node is summer Vacation. Its first (only one) child is Paris. Paris has children louver. Finally, I accessed the Catalog collection in the Louver photo directory.
Summer Vacation
Paris
Louvre
Egyptian Antiquities
Sculptures
Paintings
Obviously, the code is a little bit more complicated, and we started by creating and initializing instances of multiple entity types, adding them to the object graph by adding them to the catalog Louver, and then adding the Louver directory to the Paris directory. Finally, we add the Paris directory to the summer vacation directory. We built the entire inheritance system from the bottom up.
Once the SaveChange () method is called, all directories are inserted into the database, and I can query the data in the table to see if all the rows are correctly inserted.
For getting part of the code, we started to get a root entity, which is a directory without a father, in the example we created a summer vacation entity, but did not set it up as a child of any entity. This makes it a root node of the entire inheritance system.
Now, starting with the root node, we call another method we wrote: Print (), the print () method takes a pair of arguments, the first argument is an Picturcategory instance object, and the second argument is an integer that represents a level or depth in the inheritance system. For the root directory, summer vacation, which at the top of the inheritance system, we pass 0 to the print () method. The method call would be such prin (root,0).
In the print () method, we output the name of the directory and precede the name with the corresponding number of leading spaces, based on the depth of the directory in the inheritance system. The method of the StringBuilder class append () accepts two parameters, one is a character and an integral type, he creates a StringBuilder instance, and appends the integer parameter to the specified number of characters. In our invocation, we use spaces and the depth of the table of contents as parameters, and he returns a space string of the number of directory depths. We call StringBuilder's Sostring () method to convert the StringBuilder instance to a string instance.
Now in the recursive section, we iterate through the Children Child Directory, call the print () method for each child directory, and make sure that Levle is incremented. When we have traversed the children, we return. The final result is the output as before.
In 6-5, we'll show another way to use table expressions in a stored procedure to iterate over the graph on the storage side and then return a flattened result set.
This is the end of the topic, I hope you have the harvest. Reprint please indicate the source. Thank you.
Entity Framework 6 Recipes Chinese Translation series (6)-----chapter II using code first to model the self-referential relationship of Entity data modeling