Use emit to create a dbcontext object

Source: Internet
Author: User
Tags emit

In the example of entityframework code first, a class that inherits dbcontext is generally created, and several dbset <> attributes are declared in this class before they can be used. Recently, I have encountered a dilemma. There are many business objects in the project, most of which inherit a custom base class modelbase, if you have to declare long attributes in dbcontext in the previous method, you just want to have a simple method. In addition, if you add a subclass of modelbase, you do not want to modify the dbcontext code any more, so a thought came into being.
At first, I tried to define a method using reflection to pass in the type of the business object that I want to create. As a result, I found that there is no way for an existing class (dbcontext) add the wildcard attribute dbset <type>.
Then I tried to create a configuration class for entitytypeconfiguration <modelbase>, and then used reflection to configure the ing relationship for all subclasses in the current Assembly, the result shows that the base class is inevitably mapped to a table. Because of entitytypeconfiguration <modelbase>, it is first included in dbcontext. This is not what I expected.
So I sacrificed the killer --- emit. The basic idea is to dynamically create a subclass object that inherits dbcontext. It is determined by the passed class to create its own or its subclass dbset <> attribute, which is more controllable.
Let's use a simple example. Declare a class

    public class Author    {        public int Id { get; set; }        public string Name { get; set; }    }

If you follow the old method, the statement should have been as follows:

    public class Blog : DbContext    {        public DbSet<Author> Authors { get; set; }    }

The method is as follows.

Public static dbcontext createinstance () {assemblybuilder AB = appdomain. currentdomain. definedynamicassembly (New assemblyname ("testcontext"), assemblybuilderaccess. runandsave); modulebuilder MB = AB. definedynamicmodule ("testcontext"); // create the type of the specified name. Note that this name must comply with the EF conventions, that is, it must be consistent with the name in the connection string configuration. typebuilder TB = Mb. definetype ("blog", typeattributes. public, typeof (dbcontext); propertybuilder pbauthor = TB. defineproperty ("Authors", propertyattributes. hasdefault, typeof (dbset <> ). makegenerictype (typeof (author), null); // create a private field for reading/writing properties // do not directly declare get/set as C # source code, this is because fieldbuilder fbauthors = TB is still private after compilation. definefield ("_ authors", typeof (dbset <> ). makegenerictype (typeof (author), fieldattributes. private); // get method part system. reflection. methodattributes = system. reflection. methodattributes. public | system. reflection. methodattributes. hidebysig; methodbuilder mbget = TB. definemethod ("get_authors", methodattributes); ilgenerator IL = mbget. getilgenerator (); label Label = Il. definelabel (); Il. emit (Opcodes. ldarg_0); Il. emit (Opcodes. ldfld, fbauthors); Il. emit (Opcodes. stloc_0); Il. emit (Opcodes. br_s, label); Il. marklabel (Label); Il. emit (Opcodes. ldloc_0); Il. emit (Opcodes. RET); // Set Method Part methodbuilder mbset = TB. definemethod ("set_authors", methodattributes); mbset. setparameters (typeof (system. data. entity. dbset <> ). makegenerictype (typeof (author); parameterbuilder value = mbset. defineparameter (1, parameterattributes. none, "value"); IL = mbset. getilgenerator (); Il. emit (Opcodes. ldarg_0); Il. emit (Opcodes. ldarg_1); Il. emit (Opcodes. stfld, fbauthors); Il. emit (Opcodes. RET); // associate the defined method reference with the property. setgetmethod (mbget); pbauthor. setsetmethod (mbset); dbcontext blog = (dbcontext) activator. createinstance (TB. createtype (); Return blog ;}

The code for testing

using (DbContext blog = CreateInstance())
{
Author author = new Author { Name = "123" }; blog.Set<Author>().Add(author); blog.SaveChanges();}

To sum up, the focus of emit dbcontext creation is to create a GET/Set Method for each business object to be operated. The above code can be further refined and written as a separate method, enter different types to replace the locations occupied by author. This method is very alternative, and the performance is not ideal (it is more efficient when the number of objects is large). Therefore, you can create it once during the initialization process when using EF, when an object is changed or increased or decreased, it can be updated with migration (new feature after ef4.3.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.