Objective
Before a few articles, was recommended to the home page, and was under the blog park, the reason content is too little, then I want to write more, or to follow this frequency to write it? itself my intentions this series is to have the simplest and easiest to understand the way to carry out, each content also do not too much, so that beginners easy to understand learning, or the hype of a large beginner from the beginning to see the tail will be dizzy. So every time I focus on the concentration of the essence of the talk, of course, I am so concise, you have to learn in-depth, but also to some of the concepts to learn more deeply. We also welcome you to discuss the study together. I created a QQ group here (435498053), we can also add group communication.
Body
This article or as a previous upgrade, in fact, the previous 2-3 can be merged, but I think the direct merger is not easy to understand, first to the most basic, and then in a gradual and progressive in-depth and code aspects of the encapsulation simplification. We don't talk about it, and then the last part of the article, you remember the final written code? I'll post the code and review it.
Entity Collection Public idbset<bloguser> blogusers {get; set;} Public idbset<post> Posts {get; set;} <summary>///Rewrite configuration class////</summary>// <param name= "ModelBuilder" ></param> protected override void Onmodelcreating (Dbmodelbuilder modelBuilder) { //base. Onmodelcreating (ModelBuilder); MODELBUILDER.CONFIGURATIONS.ADD (New Bloguserconfiguration ()); MODELBUILDER.CONFIGURATIONS.ADD (New Postconfiguration ()); }
The previous article we put forward this is to simplify the onmodelcreating in the configuration of each table to write here, but the intentions of friends should see, you write this is actually still very troublesome ah! According to the current writing, do I have to create a collection of entities here, and then join a MODELBUILDER.CONFIGURATIONS.ADD (new Xxxconfiguration ()) below, so the problem remains the same. specifically see below
As can be seen from the code, the current context class is strongly coupled to the business entity, and is coupled to the dbset<tentity> attribute and onmodelcreating method respectively. What about the solution? Of course to decouple. For attributes, you can use the Dbcontext.set<tentity> () method to implement the properties of the specified entity, and for a mapping configuration object in a method implementation in Onmodelcreating, you can extract a common interface that is mapped separately through the interface. Then we'll take two steps to explain how to decouple!
One, the extraction of a Ientitymapper universal interface, through the interface to map separately.
1, the code to define the interface is as follows:
<summary>// Entity Mapping interface///</summary> public interface ientitymapper { // <summary>//// Register the current entity mapping object with the current data access context entity mapping Configuration Registrar///</summary>// <param name= " Configurations "> Entity Mapping Configuration Registrar </param> void Registto (Configurationregistrar configurations); }
2. Add the implementation of Ientitymapper to the entity mapping class. We have Bloguser as an example demonstration. The code is as follows
<summary> ///blog User Information mapping class ///</summary> public class Bloguserconfiguration: Entitytypeconfiguration<bloguser>,ientitymapper {public bloguserconfiguration () { //Set Primary key Haskey (m = M.bloguserid); } public void Registto (System.Data.Entity.ModelConfiguration.Configuration.ConfigurationRegistrar configurations) { configurations. ADD (this); throw new NotImplementedException (); } }
3, so defined, that is not to be considered how can be automatically called in onmodelcreating implementation Ientitymapper automatic registration it! There are many ways to do this, and there are friends who know that IOC should think of using dependency injection to introduce all the objects that implement the Ientitymapper class. But I'm not going to do this with the IOC component first, we'll do it in the most traditional way.
How exactly do we have to do it all? is to introduce all the objects that implement the Ientitymapper class, and then iterate through the Registto to add the entity mapping class object.
The first step is to get all the objects that implement the Ientitymapper class, see the Code
private static icollection<ientitymapper> Getallentitymapper () {icollection<assembly > entitymapperassemblies = entitymapperassemblies = new[] {Assembly. LoadFrom (Path.Combine (AppDomain.CurrentDomain.RelativeSearchPath, "EFCore.dll")}; if (Entitymapperassemblies.count = = 0) {throw new InvalidOperationException ("context" {0} "initialization failed, please add the actual Volume mapping assembly "); } Type BaseType = typeof (Ientitymapper); type[] Mappertypes = entitymapperassemblies.selectmany (assembly = assembly. GetTypes ()). Where (type = Basetype.isassignablefrom (type) && type! = BaseType &&!type. IsAbstract). ToArray (); icollection<ientitymapper> result = Mappertypes.select (type = Activator.CreateInstance (type) as Ientitymapper). ToList (); return result; }
Above this paragraph I refer to someone else's code, specific which blog I do not remember, then find me on the Add Reference. The principle is also relatively simple is I load I write entity class EFCore.dll assembly, this DLL name is based on the DLL name of your actual project, this name is now my own demo. It then finds the class that implements Ientitymapper and then creates an instance of that type through CreateInstance, which is the principle.
The second step, traversing the object, calls the Registto in which the entity mapping class object is added
<summary>///Rewrite configuration class////</summary>// <param name= "ModelBuilder" ></param> protected override void Onmodelcreating (Dbmodelbuilder modelBuilder) { //base. Onmodelcreating (ModelBuilder); MODELBUILDER.CONFIGURATIONS.ADD (New Bloguserconfiguration ()); MODELBUILDER.CONFIGURATIONS.ADD (New Postconfiguration ()); Modelbuilder.entity<bloguser> (). Haskey (M = m.bloguserid); ienumerable<ientitymapper> entitymappers = Getallentitymapper (); if (entitymappers = = null) { return; } foreach (var mapper in entitymappers) { mapper. Registto (modelbuilder.configurations); } }
Then it's done, run your code. Did it succeed too.
I put the complete code in the attached
<summary>///Rewrite configuration class///</summary>//<param name= "ModelBuilder" ></ param> protected override void Onmodelcreating (Dbmodelbuilder modelBuilder) {//base. Onmodelcreating (ModelBuilder); MODELBUILDER.CONFIGURATIONS.ADD (New Bloguserconfiguration ()); MODELBUILDER.CONFIGURATIONS.ADD (New Postconfiguration ()); Modelbuilder.entity<bloguser> (). Haskey (M = M.bloguserid); ienumerable<ientitymapper> entitymappers = Getallentitymapper (); if (entitymappers = = null) {return; } foreach (var mapper in entitymappers) {mapper. Registto (modelbuilder.configurations); }} private static Icollection<ientitymapper> Getallentitymapper () {icollection< assembly> entitymapperassemblies = Entitymapperassemblies = new[] {Assembly.LoadFrom (Path.Combine (AppDomain.CurrentDomain.RelativeSearchPath, "EFCORE.D ll "))}; if (Entitymapperassemblies.count = = 0) {throw new InvalidOperationException ("context" {0} "initialization failed, please add the actual Volume mapping assembly "); } Type BaseType = typeof (Ientitymapper); type[] Mappertypes = entitymapperassemblies.selectmany (assembly = assembly. GetTypes ()). Where (type = Basetype.isassignablefrom (type) && type! = BaseType &&!type. IsAbstract). ToArray (); icollection<ientitymapper> result = Mappertypes.select (type = Activator.CreateInstance (type) as Ientitymapper). ToList (); return result; }
As a demo, I don't want to create a new class to encapsulate, so it's easy to read.
Second, for attributes, you can use the Dbcontext.set<tentity> () method to implement the properties of the specified entity
Above, we realize the decoupling of the code inside the onmodelcreating by advancing a Ientitymapper interface. So here we have to find a way to deal with the code below.
Public idbset<bloguser> blogusers {get; set;} Public idbset<post> Posts {get; set;} ......
As mentioned above, the solution is to implement the properties of the specified entity through the dbcontext.set<tentity> () method, how to do it? In fact, this is much simpler than processing the configuration class, of course, or directly look at the code.
Public ActionResult Index () { var db= new Blogdbcontext (); Return View (db. Posts.tolist ());}
This code is the first one inside, gets the data inside the posts, and then returns the foreground display. Do you remember? Don't remember to turn to the first article to see.
The code above has been seen in the first one, and if it's decoupled, it's in db. Posts does not exist, then how to do it! Same look at the code
Public ActionResult Index () { var dbContext = new Blogdbcontext (); IQueryable
<Post> Posts = dbcontext.set<post>
(); Return View (Posts.tolist ()); }
This is what it says. Use the Dbcontext.set<tentity> () method to implement the properties of the specified entity. Is it simple? A word can be done.
Finally, I'll post our final source code.
Public Blogdbcontext (): Base () {}///entity Collection//public idbset<bloguser> blogusers {g Et Set }//public idbset<post> Posts {get; set;} <summary>///Rewrite configuration class///</summary>//<param name= "ModelBuilder" ></param> ; protected override void Onmodelcreating (Dbmodelbuilder modelBuilder) {//base. Onmodelcreating (ModelBuilder); MODELBUILDER.CONFIGURATIONS.ADD (New Bloguserconfiguration ()); MODELBUILDER.CONFIGURATIONS.ADD (New Postconfiguration ()); Modelbuilder.entity<bloguser> (). Haskey (M = M.bloguserid); ienumerable<ientitymapper> entitymappers = Getallentitymapper (); if (entitymappers = = null) {return; } foreach (var mapper in entitymappers) {mapper. Registto (modelbuilder.configurations); } }private static icollection<ientitymapper> Getallentitymapper () {icollection<assembly> Entit Ymapperassemblies = Entitymapperassemblies = new[] {assembly.loadfrom (P Ath. Combine (AppDomain.CurrentDomain.RelativeSearchPath, "EFCore.dll")}; if (Entitymapperassemblies.count = = 0) {throw new InvalidOperationException ("context" {0} "initialization failed, please add the actual Volume mapping assembly "); } Type BaseType = typeof (Ientitymapper); type[] Mappertypes = entitymapperassemblies.selectmany (assembly = assembly. GetTypes ()). Where (type = Basetype.isassignablefrom (type) && type! = BaseType &&!type. IsAbstract). ToArray (); icollection<ientitymapper> result = Mappertypes.select (type = Activator.CreateInstance (type) as Ientitymapper). ToList (); return result; }
Now if you add a new entity class, you don't have to change any of the code here. has been completely decoupled. Isn't it pretty simple.
Conclusion
After this article, in fact, the most basic version of EF learning is finished. The previous few also hope that beginners can master. In the following words to explain in depth, then will talk about the IOC, and Repository,unitofwork,dbcontext. These are also used in our official projects.
You are welcome to exchange. More support. QQ Group (435498053)
Step by Step EF Series "4, upgrade entity and database mapping" Live writer Real Pit, 4th time reissue