MVC + EF + Autofac (dbfirst) Lightweight project framework, autofacdbfirst
Preface
I used to use another person's open-source project framework all the time. It would be very troublesome to locate exceptions, and I don't even know whether the exception comes from my code or the framework itself. Others' frameworks have certain constraints, and I may not have a deep understanding of those frameworks, because these open-source frameworks are difficult to find efficient and standardized documents on the Internet. For example, another framework may call the Enterprise Library to verify permissions. However, in my project, permission verification has Reusable Modules, so it is not flexible to integrate ....
After reading many excellent frameworks on the Internet and reading a few books, I suddenly realized that easy-to-use is the starting point and foothold for developing and using frameworks. The framework is not as complicated as it is, so I can evaluate the quality of a framework, the learning cost, use cost and maintenance cost should be taken into account comprehensively. After considering the above factors, I plan to build a lightweight framework to facilitate future expansion. Although the framework is already very simple, there may still be problems.
Development Background
The project I want to deal with does not have a particularly complex business logic. The biggest problem to face is high concurrency. This is also an important reason for me to discard the original framework.
Because the business logic is not complex, the dbfirst design concept is adopted. On the one hand, it is easier for others to get started during subsequent project development, and on the other hand, I am only stuck in the usable phase for codefirst, deep understanding of DDD is still very limited, and many wrong ways of thinking may be introduced.
The development environment of the Project is Windows 7 SP1, Visual Studio 2013, SQL Server 2012, and. NET Framework4.5.
The project relies on ASP. net mvc + WebAPI and uses EntityFramework for data storage.
Overall framework
This is a project solution. It consists of the WEB layer, Core layer, Model layer, and Infrastructure layer. The functions are as follows:
The project dependency is like this, using Autofac injection. Originally, spring.net was used. This time, Autofac is more lightweight for dependency injection, which is more efficient (as mentioned on the Internet (-:), and many help documents can also be found. In addition, Autofac provides mvc a solution that uses every request as the basis for injection. It is very practical to pass an object into the Controller as a parameter.
Creation process
In the Entity assembly, edmx is generated through the database, which also contains the object model. Create the DbContext object of the Entities in the core.
In my original system, I usually create a DAL (database access layer) on EF to store common methods for adding, deleting, modifying, and querying data, however, I gradually realized that the EF framework itself has effectively encapsulated the methods in the traditional DAL layer. If we put a DAL layer, it would be too much of a repeated encapsulation. We will not discuss in detail whether this layer of DAL encapsulation is necessary, because different people may have different habits. If you come from a traditional three-tier architecture, it may be easier to put a DAL, of course, it also has the advantages of not releasing. For example, the business can be more flexible when operating the database, and the layer interface can be more intuitive when coding. However, the database operations cannot be encapsulated without DAL, which leads to another seemingly tricky problem. If you change the database in the future, do you need to change the code in the core layer? This will lead to high coupling. I had been entangled in this issue for a long time, but I thought about it again. Entity framework is an open-source framework that is supported by mainstream databases, including oracle, to change the database, you only need to regenerate the edmx of the corresponding database type, which has no impact on the business core.
I created a CoreSession class at the business layer to store the set of web business operations.
The following is an interface.
1 public interface ICoreSession2 {3
4 }
The following is the implementation, which contains a db attribute, stores the Entity object after the instance, and creates an instance in the most constructor.
1 public class CoreSession:EDUA_ICore.ICoreSession 2 { 3 private DbContext db { get; set; } 4 public CoreSession() 5 { 6 db = new Entity.EDUAEntities(); 7 } 8 public int SaveChanges() 9 {10 return db.SaveChanges();11 }12 }
The most simple core layer is built, although there is no way in it. Create a core object in the web layer. Can the core be a singleton in the web layer? Core Singleton means EF entity Singleton, because EF instance process is in the core constructor. However, EF itself cannot guarantee thread security. When I discussed with my predecessors that day that EF shouldn't be a Singleton, almost both of them told me never to do it at the same time. They all made a move. If we use the simplest static method to implement single, it is not only high concurrency, but also a problem as long as the concurrency occurs. Of course, there is another method. callcontext is used to put the core object into the thread and get it from the thread every time. This method is used to ensure the thread security of EF, this is a more reliable Singleton method I have used, and there is no problem yet. However, to ensure high concurrency performance and learn from the mechanism provided by Autofac (Ioc), I decided to create a Core object for each request.
The procedure for configuring Autofac is as follows:
1. Download and introduce the Autofac assembly
: Http://autofac.org/
Here we need to introduce these two sets on the WEB. The former is the core of autofac, and the latter is its mvc plug-in. If we need to write the injected ing object to the configuration file, we also need to introduce Autofac. configuration. dll assembly, Because I directly write the ing in the Code, there is no reference.
2. Create the RegisterAutofacForSingle class in the web layer. Although the class name is single, it is only the single at registration, not to mention the object Singleton.
1 public class RegisterAutofacForSingle 2 {3 public static void RegisterAutofac () 4 {5 ContainerBuilder builder = new ContainerBuilder (); 6 builder. registerControllers (Assembly. getExecutingAssembly (); 7 8 // register with controller 9 builder. registerType <EDUA_Core.CoreSession> (). as <EDUA_ICore.ICoreSession> (). instancePerHttpRequest (); 10 11 // register with the filter 12 builder. registerType <EDUA_Core.CoreSession> (). as <EDUA_ICore.ICoreSession> (); 13 builder. registerType <Filters. myAuthorizeAttribute> (). singleInstance (); 14 builder. registerFilterProvider (); 15 16 var container = builder. build (); 17 DependencyResolver. setResolver (new AutofacDependencyResolver (container); 18} 19 20}
Row 6th registers the Controller version. Row 9th uses the InstancePerHttpRequest () method to create a new instance for each new request. The behavior registered to the filter is global Singleton, because there is no write operation in my filter, and there is no read/write problem in concurrency.
3. Register Autofac in the Globa. asax File
1 public class MvcApplication: System. web. httpApplication 2 {3 protected void Application_Start () 4 {5 // register Autofac 6 RegisterAutofacForSingle. registerAutofac (); 7 8 AreaRegistration. registerAllAreas (); 9 10 WebApiConfig. register (GlobalConfiguration. configuration); 11 FilterConfig. registerGlobalFilters (GlobalFilters. filters); 12 RouteConfig. registerRoutes (RouteTable. routes); 13 BundleConfig. registerBundles (BundleTable. bundles); 14} 15}
It should be noted that, because RegisterAutofacForSingle registers injection for the filter, you must register Autofac before registering the filter. Otherwise, an error will be reported. I put Autofac registration at the beginning.
4. Add a core object instance to the Controller and filter.
1 private ICoreSession iCoreSession;2 public MyAuthorizeAttribute(ICoreSession iCoreSession)3 {4 this.iCoreSession = iCoreSession;5 }
So far, you can directly call the content in the core in the Controller and filter.
In the next article, I will give a login example to expand the core layer and implement permission judgment in the filter.