Step by step create ASP.NET MVC5 program [Repository+Autofac+Automapper+SqlSugar] (6)

Keywords: ASP.NET Database github less

Preface

Hello, everyone. I'm Rector.

It's Friday again, very excited, very happy, very high.........
Rector meets you again in Tuheng!!! Last article Step by step to create ASP.NET MVC5 program [Repository+Autofac+Automapper+SqlSugar] (V) We have completed:

  • What is AutoMapper
  • Install AutoMapper
  • Configuration of AutoMapper
  • Application of AutoMapper

Through the study of the previous articles, the main technologies and components involved in this series [Repository+Autofac+Automapper+SqlSugar], which creates ASP.NET MVC5 program step by step], have been basically introduced. The next series of articles will focus on the integration, upgrading and reconstruction of knowledge and technology. By solving various problems encountered in the actual project, we can help you to have a clear vision and study in a directional way, so as to achieve the effect of improving your ASP.NENT MVC 5 development skills.

Points of knowledge in this paper

What I want to share with you today is the advanced knowledge of this series [creating ASP.NET MVC5 program step by step]:

  • Generic storage

Why use generic warehousing

When it comes to why generic warehousing is used, we have to go back to our project and drive it by project design to explain why generic warehousing is and what benefits generic warehousing has.

Back to the project itself

In v1.5 version, we have realized the storage reservoir and service layer. Among them, warehouse reservoir is the layer where we directly access the database. We can do any authorized operation on the database through warehouse reservoir, including adding, deleting, modifying and checking. Our PostRepository Blog Storage Implementation Class has implemented the add, delete, change, check operation, IPostRepository interface:

using System.Collections.Generic;
using TsBlog.Domain.Entities;

namespace TsBlog.Repositories
{
    public interface IPostRepository
    {
        /// <summary>
        /// Query individual data based on ID
        /// </summary>
        /// <param name="id">ID</param>
        /// <returns></returns>
        Post FindById(int id);
        /// <summary>
        /// Query all data (no pagination, use cautiously in large quantities)
        /// </summary>
        /// <returns></returns>
        IEnumerable<Post> FindAll();

        /// <summary>
        /// Write Entity Data
        /// </summary>
        /// <param name="entity">blog entity class </param>
        /// <returns></returns>
        int Insert(Post entity);

        /// <summary>
        ///Update entity data
        /// </summary>
        /// <param name="entity">blog entity class </param>
        /// <returns></returns>
        bool Update(Post entity);

        /// <summary>
        /// Delete a data by entity
        /// </summary>
        /// <param name="entity">blog entity class </param>
        /// <returns></returns>
        bool Delete(Post entity);

        /// <summary>
        /// Delete the data for the specified ID
        /// </summary>
        /// <param name="id">primary key ID</param>
        /// <returns></returns>
        bool DeleteById(object id);

        /// <summary>
        /// Delete data from the specified ID collection (bulk deletion)
        /// </summary>
        ///<param name="ids">primary key ID set </param>
        /// <returns></returns>
        bool DeleteByIds(object[] ids);
    }
}

Looking at this interface class file now, if we add a new user table to the database and then create a corresponding domain entity (User) in the domain project [TsBlog.Domain], do we need to create an IUser Repository. CS in the warehouse according to the steps of adding warehouse and service layer interfaces before this series, if IUser Repository also includes it? Add, delete, change, check methods, then do we need to copy all the interface methods in IPostRepository to the IUserRepository.cs file? At the same time, its implementation also needs the same replication.

If we add more tables to the database, will the corresponding storage interface and implementation repeat the above? CTRL + c, Ctrl + v!!!! If so, it's better to use a code generator.

Seeing this, I hope developers with development experience don't joke. Think back to what I did when I first entered. NET development. Copy, paste and code generator were used. With the accumulation of time and experience, you will also become better, if you use less or do not need to copy, paste to achieve coding functions, even if the implementation of online search methods, also have to do it yourself.

The above two paragraphs are off the point, but we still get back to the point. The problems mentioned above are actually ways to avoid duplication of work and reduce our workload, even with generic warehousing.

Implementation of generic warehousing

First, open the project [TsBlog.Repositories], create the interface file IRepository.cs, and write a general query interface method in it:

using System;
using System.Collections.Generic;
using System.Linq.Expressions;

namespace TsBlog.Repositories
{
    /// <summary>
    ///Warehouse Universal Interface Class
    /// </summary>
    /// <typeparam name="T">generic entity class </typeparam>
    public interface IRepository<T> where T : class, new()
    {
        /// <summary>
        /// Query individual data based on primary values
        /// </summary>
        /// <param name="pkValue">primary key value </param>
        /// returns > generic entities </returns >
        T FindById(object pkValue);

        /// <summary>
        /// Query all data (no pages, please use carefully)
        /// </summary>
        /// <returns></returns>
        IEnumerable<T> FindAll();
        /// <summary>
        /// Query data according to conditions
        /// </summary>
        /// <param name="predicate">conditional expression tree </param>
        /// <param name="orderBy">sort </param>
        /// returns > generic entity set </returns >
        IEnumerable<T> FindListByClause(Expression<Func<T, bool>> predicate, string orderBy);

        /// <summary>
        /// Query data according to conditions
        /// </summary>
        /// <param name="predicate">conditional expression tree </param>
        /// <returns></returns>
        T FindByClause(Expression<Func<T, bool>> predicate);

        /// <summary>
        /// Write Entity Data
        /// </summary>
        /// <param name="entity">entity class </param>
        /// <returns></returns>
        long Insert(T entity);

        /// <summary>
        ///Update entity data
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        bool Update(T entity);

        /// <summary>
        ///Delete data
        /// </summary>
        /// <param name="entity">entity class </param>
        /// <returns></returns>
        bool Delete(T entity);
        /// <summary>
        ///Delete data
        /// </summary>
        /// <param name="where">filtration condition </param>
        /// <returns></returns>
        bool Delete(Expression<Func<T, bool>> @where);

        /// <summary>
        /// Delete the data for the specified ID
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        bool DeleteById(object id);

        /// <summary>
        /// Delete data from the specified ID collection (bulk deletion)
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        bool DeleteByIds(object[] ids);
    }
}

Create generic base class GenericRepository.cs:

using System;
using System.Collections.Generic;
using System.Linq.Expressions;

namespace TsBlog.Repositories
{
    public abstract class GenericRepository<T> : IRepository<T> where T : class, new()
    {
        #region Implementation of IRepository<T>

        /// <summary>
        /// Query individual data based on primary values
        /// </summary>
        /// <param name="pkValue">primary key value </param>
        /// returns > generic entities </returns >
        public T FindById(object pkValue)
        {
            using (var db = DbFactory.GetSqlSugarClient())
            {
                var entity = db.Queryable<T>().InSingle(pkValue);
                return entity;
            }
        }

        /// <summary>
        /// Query all data (no pages, please use carefully)
        /// </summary>
        /// <returns></returns>
        public IEnumerable<T> FindAll()
        {
            using (var db = DbFactory.GetSqlSugarClient())
            {
                var list = db.Queryable<T>().ToList();
                return list;
            }
        }

        /// <summary>
        /// Query data according to conditions
        /// </summary>
        /// <param name="predicate">conditional expression tree </param>
        /// <param name="orderBy">sort </param>
        /// returns > generic entity set </returns >
        public IEnumerable<T> FindListByClause(Expression<Func<T, bool>> predicate, string orderBy)
        {
            using (var db = DbFactory.GetSqlSugarClient())
            {
                var entities = db.Queryable<T>().Where(predicate).ToList();
                return entities;
            }
        }

        /// <summary>
        /// Query data according to conditions
        /// </summary>
        /// <param name="predicate">conditional expression tree </param>
        /// <returns></returns>
        public T FindByClause(Expression<Func<T, bool>> predicate)
        {
            using (var db = DbFactory.GetSqlSugarClient())
            {
                var entity = db.Queryable<T>().First(predicate);
                return entity;
            }
        }

        /// <summary>
        /// Write Entity Data
        /// </summary>
        /// <param name="entity">entity class </param>
        /// <returns></returns>
        public long Insert(T entity)
        {
            using (var db = DbFactory.GetSqlSugarClient())
            {
                //Returns the ID field value of the inserted data
                var i = db.Insertable(entity).ExecuteReturnBigIdentity();
                return i;
            }
        }

        /// <summary>
        ///Update entity data
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public bool Update(T entity)
        {
            using (var db = DbFactory.GetSqlSugarClient())
            {
                //This approach is conditioned on the primary key.
                var i = db.Updateable(entity).ExecuteCommand();
                return i > 0;
            }
        }

        /// <summary>
        ///Delete data
        /// </summary>
        /// <param name="entity">entity class </param>
        /// <returns></returns>
        public bool Delete(T entity)
        {
            using (var db = DbFactory.GetSqlSugarClient())
            {
                var i = db.Deleteable(entity).ExecuteCommand();
                return i > 0;
            }
        }

        /// <summary>
        ///Delete data
        /// </summary>
        /// <param name="where">filtration condition </param>
        /// <returns></returns>
        public bool Delete(Expression<Func<T, bool>> @where)
        {
            using (var db = DbFactory.GetSqlSugarClient())
            {
                var i = db.Deleteable<T>(@where).ExecuteCommand();
                return i > 0;
            }
        }

        /// <summary>
        /// Delete the data for the specified ID
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public bool DeleteById(object id)
        {
            using (var db = DbFactory.GetSqlSugarClient())
            {
                var i = db.Deleteable<T>(id).ExecuteCommand();
                return i > 0;
            }
        }

        /// <summary>
        /// Delete data from the specified ID collection (bulk deletion)
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        public bool DeleteByIds(object[] ids)
        {
            using (var db = DbFactory.GetSqlSugarClient())
            {
                var i = db.Deleteable<T>().In(ids).ExecuteCommand();
                return i > 0;
            }
        }

        #endregion
    }
}

Now that the warehouse interface and generic warehouse base classes have been created, let's reconstruct IPostRepository and PostRepository to inherit them from IRepository and GenericRepository, respectively.

IPostRepository.cs

using TsBlog.Domain.Entities;

namespace TsBlog.Repositories
{
    public interface IPostRepository :IRepository<Post>
    {

    }
}

PostRepository.cs

using TsBlog.Domain.Entities;

namespace TsBlog.Repositories
{
    /// <summary>
    /// Database Operations Classes for POST Tables
    /// </summary>
    public class PostRepository : GenericRepository<Post>
    {
       
    }
}

Is IPostRepository and PostRepository much simpler, but the implementation method is the same as before the reconstruction?

So, if we add the storage interface and storage implementation of user tables, is it very simple? It is no longer necessary to duplicate, delete, change and check operations to copy and paste.

Configuring Interface-based Dependency Injection

Add the interface class IDependency.cs to the project [TsBlog.Repositories]:

namespace TsBlog.Repositories
{
    /// <summary>
    ///Dependency Injection Interface Constraints
    /// </summary>
    public interface IDependency
    {
    }
}

Add IDependency interface constraints to GenericRepository.cs, a generic warehouse abstract base class:

public abstract class GenericRepository<T> : IDependency, IRepository<T> where T : class, new()

Open Global.asax in the project TsBlog.Frontend to reconfigure the AutofacRegister method as follows:

private void AutofacRegister()
{
    var builder = new ContainerBuilder();

    //Register all controllers in the Mvc Application assembly
    builder.RegisterControllers(typeof(MvcApplication).Assembly);

    //Registered Warehouse Reservoir Service
    //builder.RegisterType<PostRepository>().As<IPostRepository>();
    
    //Register entities based on interface constraints
    var assembly = AppDomain.CurrentDomain.GetAssemblies();
    builder.RegisterAssemblyTypes(assembly)
        .Where(
            t => t.GetInterfaces()
                .Any(i => i.IsAssignableFrom(typeof(IDependency)))
        )
        .AsImplementedInterfaces()
        .InstancePerDependency();
    
    //Registration Service Layer Service
    builder.RegisterType<PostService>().As<IPostService>();

    //Registration filter
    builder.RegisterFilterProvider();

    var container = builder.Build();

    //Setting Dependency Injection Parser
    DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}

Running according to F5, did you report an error?
Yes, because we just modified the return type of Insert in generic warehouse, so we changed the return type of Insert in IPostService.cs to long:

long Insert(Post entity);

Modified IPostService.cs:

using System.Collections.Generic;
using TsBlog.Domain.Entities;

namespace TsBlog.Services
{
    public interface IPostService
    {
        /// <summary>
        /// Query individual data based on ID
        /// </summary>
        /// <param name="id">ID</param>
        /// <returns></returns>
        Post FindById(int id);
        /// <summary>
        /// Query all data (no pagination, use cautiously in large quantities)
        /// </summary>
        /// <returns></returns>
        IEnumerable<Post> FindAll();

        /// <summary>
        /// Write Entity Data
        /// </summary>
        /// <param name="entity">blog entity class </param>
        /// <returns></returns>
        long Insert(Post entity);

        /// <summary>
        ///Update entity data
        /// </summary>
        /// <param name="entity">blog entity class </param>
        /// <returns></returns>
        bool Update(Post entity);

        /// <summary>
        /// Delete a data by entity
        /// </summary>
        /// <param name="entity">blog entity class </param>
        /// <returns></returns>
        bool Delete(Post entity);

        /// <summary>
        /// Delete the data for the specified ID
        /// </summary>
        /// <param name="id">primary key ID</param>
        /// <returns></returns>
        bool DeleteById(object id);

        /// <summary>
        /// Delete data from the specified ID collection (bulk deletion)
        /// </summary>
        ///<param name="ids">primary key ID set </param>
        /// <returns></returns>
        bool DeleteByIds(object[] ids);
    }
}

Modify the return type of Insert in PostService.cs to long:

public long Insert(Post entity)
{
      return _postRepository.Insert(entity);
}

Modified PostService.cs:

using System.Collections.Generic;
using TsBlog.Domain.Entities;
using TsBlog.Repositories;

namespace TsBlog.Services
{
    public class PostService : IPostService
    {
        private readonly IRepository<Post> _postRepository;
        public PostService(IRepository<Post> postRepository)
        {
            _postRepository = postRepository;
        }
        public bool Delete(Post entity)
        {
            return _postRepository.Delete(entity);
        }

        public bool DeleteById(object id)
        {
            return _postRepository.DeleteById(id);
        }

        public bool DeleteByIds(object[] ids)
        {
            return _postRepository.DeleteByIds(ids);
        }

        public IEnumerable<Post> FindAll()
        {
            return _postRepository.FindAll();
        }

        public Post FindById(int id)
        {
            return _postRepository.FindById(id);
        }

        public long Insert(Post entity)
        {
            return _postRepository.Insert(entity);
        }

        public bool Update(Post entity)
        {
            return _postRepository.Update(entity);
        }
    }
}

Note: IPostRepository.cs has not been inherited in PostRepository.cs, so we temporarily use the generic interface IRepository in the constructor of PostService.cs:

private readonly IRepository<Post> _postRepository;
public PostService(IRepository<Post> postRepository)
{
    _postRepository = postRepository;
}

The next article will address this problem.

Press F5 again and open the page. http://localhost:54739/home/post ], familiar with your page is back, haha...

This article's source hosting address: https://github.com/lampo1024/TsBlog/releases/tag/v1.6

This is the end of this article. This series is not finished yet. See you next time.

If you like Rector's article series, please give me a big compliment.

Source of this article Picture sharing network <Step by step create ASP.NET MVC5 program [Repository+Autofac+Automapper+SqlSugar] (6)>

Posted by GaryAC on Sat, 15 Dec 2018 10:39:03 -0800