Use MVC5 + EF6 + WebApi for an exam function (6) Create an EF general warehouse class in the warehouse mode, mvc5ef6

Source: Internet
Author: User

Use MVC5 + EF6 + WebApi for an exam function (6) Create an EF general warehouse class in the warehouse mode, mvc5ef6
Preface

Work is busy at the end of the year, the annual summary has not yet been written, the project should be launched, and various preparations should be made back to your hometown for the New Year. In particular, it is too big to prepare gifts for elders to give their nephews and nities.

I thought I could use the first version a year ago. I thought it was a bit suspended. I tried to get out the general functions first, and threw away some items to ensure that I could take the test, and then I made some extensions.

This section mainly describes EF encapsulation. In the DDD design, there are two concepts that have to be mentioned: Work Unit mode and storage mode. This is my personal understanding. If it is not correct, you can communicate with us.

The following figure is from the Microsoft documentation site.

 

Warehouse mode definition
 

The Repository mode is used to manage CRUD operations through abstract interfaces. This interface exposes domain entities and hides Implementation Details of database access code.

Why?

In fact, the definition has been quite clear. It is encapsulated to let the previous layer not know how data access is implemented. Why? Then we will go back to the concept of DDD. In the congestion model, we will focus more on the implementation of business functions rather than the data persistence layer. In the previous three layers, DAL actually focuses on how to extract data, how to save it. In order to avoid returning to the middle of the three-tier architecture, DDD identifies persistence as a layer. The separation between this layer and the business is through the warehousing mode.

Generally, the warehousing interface is provided in the field, that is, what to do. The specific implementation is handed over to the persistence layer. As for the persistence layer, ADO is used. NET still uses the ORM framework, and data is stored in RDBMS, XML, JSON, Cache, or Nosql. These are irrelevant to the domain model. The domain model only cares about the interface and whether it is implemented, this ensures the independence between the domain model and data persistence.

Advantages

Reference: Why the Repository Pattern

 

Work Unit mode definition
 

Maintains a list of objects affected by a business transaction and coordinates the writing out of changes and the resolution of concurrency problems.   --P of EAA – Martin Fowler

The "unit of work" mode is used to group one or more operations (usually database operations) to a single transaction or a "unit of work" so that all operations can pass or fail. -- Free translation by netizens.

Why?

The work unit is to ensure the atomicity of business operations, that is, when a consistent business is submitted, either all succeed or all fail, for example, when a user places an order, to generate orders, reduce inventory, deliver logistics, and analyze services, the three operations are completed at the same time. They cannot be separated, either succeed or fail.

Entity Framework itself has this feature. In an operation, onlyDb. SaveChanges ()The operation will be saved, and the operation will succeed or fail at the same time. Since EF itself and has this function, why should we create a work unit?

There is a storage mode. When a single object operation adds, deletes, modifies, and queries, there is no problem. However, when an operation involves multiple object models, there will be multiple DbContext, there are a lot of repeated code, and code for cross-entity Operations is nowhere to be placed.

For example, for a User Creation operation, the following two tables (this example is not very appropriate, so you can understand it in general ):

When registering a user, it is possible to enter information in a distributed manner. At last, you must add two entities and one account to record one user information record.

In the account storage class, I can add a record and a record in the user information warehouse. At last, the two records cannot be both successful or failed.

Implementation
Public interface IUnitOfWork {// <summary> /// command // </summary> /// <param name = "commandText"> </param> /// <param name = "parameters"> </param> // <returns> </returns> int Command (string commandText, IDictionary <string, object> parameters); // <summary> // transaction submission status /// </summary> bool IsCommited {get; set ;} /// <summary> /// submit the transaction /// </summary> /// <returns> </returns> void Commit (); /// <summary> /// roll back the transaction // </summary> void RollBack ();}

 

This section text-General Storage Class implementation

I found that every time I sorted it out, I couldn't do it. I 've spent a lot of energy on the warehousing model and work unit. In fact, I didn't use a work unit in my project because the project is relatively small, if you need a work unit, define an excuse in the warehouse to solve the problem. There is also the previous work unit + Ioc mode, in addition to poor debugging, in order to ensure the project progress, first implement the function, and then refactor it.

 

First, the warehousing mode is the implementation of an interface and an interface. we add the IRepository interface to the Domain project. The definition is as follows:

public interface IRepository<TEntity> where TEntity : class    {        IQueryable<TEntity> All();        TEntity Single(long id);        TEntity Single(Expression<Func<TEntity, bool>> predicate);        TEntity Single(long id, params Expression<Func<TEntity, object>>[] propertySelectors);        IQueryable<TEntity> Find(Expression<Func<TEntity, bool>> predicate);        IQueryable<TEntity> Find(Expression<Func<TEntity, bool>> predicate, params Expression<Func<TEntity, object>>[] propertySelectors);        int Count();        int Count(Expression<Func<TEntity, bool>> criteria);        IEnumerable<TEntity> Get<TOrderBy>(Expression<Func<TEntity, bool>> criteria, Expression<Func<TEntity, TOrderBy>> orderBy, int pageIndex, int pageSize, SortOrder sortOrder = SortOrder.Ascending);        TEntity Delete(long id);        bool Add(TEntity entity);        bool Update(TEntity entity);        int Save(TEntity entity);    }

The interface defines various operations for addition, deletion, modification, and query. All implementations are on the persistence layer. Here we encapsulate them and provide a general storage class as follows:

Public class GenericRepository <TEntity>: IRepository <TEntity> where TEntity: EneityOfLongPrimarykey {private MyDbContext context; public GenericRepository () {context = new MyDbContext (); // Load navigation properties explicitly (avoid serialization trouble) context. configuration. lazyLoadingEnabled = false; // Do NOT enable proxied entities, else serialization fails. context. configuration. proxyC ReationEnabled = false; // Because Web API will perform validation, we don't need/want EF to do so context. configuration. validateOnSaveEnabled = false;} public virtual IQueryable <TEntity> All () {return context. set <TEntity> (). asQueryable ();} public TEntity Single (long id) {return All (). single (t => t. id = id);} public TEntity Single (long id, params Expression <Func <TEntity, object> [] propertyS Electors) {return Find (s => s. id = id, propertySelectors ). firstOrDefault ();} public TEntity Single (Expression <Func <TEntity, bool> predicate) {return All (). single (predicate);} public IQueryable <TEntity> Find (Expression <Func <TEntity, bool> predicate) {if (predicate! = Null) {return All (). where (predicate ). asNoTracking () ;}else {return All () ;}/// <summary> // filter data, enable delayed query /// </summary> /// <param name = "predicate"> filter condition </param> /// <param name = "propertySelectors"> Left join table </param> /// <returns> </returns> public IQueryable <TEntity> Find (Expression <Func <TEntity, bool> predicate, params Expression <Func <TEntity, object> [] propertySelectors) {if (prope RtySelectors. isNullOrEmpty () {return Find (predicate);} var query = Find (predicate); foreach (var propertySelector in propertySelectors) {query = query. include (propertySelector);} return query;} public int Count () {return All (). count ();} public int Count (Expression <Func <TEntity, bool> criteria) {return All (). count (criteria);} public IEnumerable <TEntity> Get <TOrderBy> (Expression <Func <TEnt Ity, bool> criteria, Expression <Func <TEntity, TOrderBy> orderBy, int pageIndex, int pageSize, SortOrder sortOrder = SortOrder. ascending) {if (sortOrder = SortOrder. ascending) {return All (). orderBy (orderBy ). skip (pageIndex-1) * pageSize ). take (pageSize ). asEnumerable ();} return All (). orderByDescending (orderBy ). skip (pageIndex-1) * pageSize ). take (pageSize ). asEnumerable ();} public TEntity De Lete (long id) {var entity = Single (id); context. set <TEntity> (). remove (entity); context. saveChanges (); return entity;} public bool Add (TEntity entity) {if (context. entry <TEntity> (entity ). state! = EntityState. detached) {context. entry <TEntity> (entity ). state = EntityState. added;} context. set <TEntity> (). add (entity); return context. saveChanges ()> 0;} public bool Update (TEntity entity) {if (context. entry <TEntity> (entity ). state! = EntityState. detached) {context. set <TEntity> (). attach (entity);} context. entry <TEntity> (entity ). state = EntityState. modified; return context. saveChanges ()> 0;} public int Save (TEntity entity) {return context. saveChanges ();}}

 

Usage:

Warehousing interface for exam subjects

/// <Summary> // warehouse layer interface -- ExamSubject // </summary> public partial interface IExamSubjectRepository: IRepository <ExamSubject> {}

 

Warehousing interface implementation for exam subjects:

Using Trump. domain. entities; using Trump. EF. common; namespace Trump. EF. repository {// <summary> // warehousing implementation -- ExamQuestionBizType // </summary> public partial class ExamSubjectRepository: GenericRepository <ExamSubject>, IExamSubjectRepository {}}

If there are no other operations except CRUD in this entity model, then the two classes are completed.

Final project:

 

In constant sorting, you can sort out some functions when you are free of time. The source code will be provided after the entire function is implemented.

Related Article

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.