.NETCore+EF+MySql+Autofac简单三层架构

前言

其实就是一个简单依赖注入的三层架构。记录一下,大佬们就不用看下去了。重点在最后面,可以直接拖到底去看。

正文

1、贴代码

1、整体的一个结构。大佬们应该一眼就看明白了。

.NETCore+EF+MySql+Autofac简单三层架构

2、MySqlContext

using  Model;
using Microsoft.EntityFrameworkCore;

namespace  DbFactory
{
    public class MySqlContext : DbContext
    {
        public MySqlContext(DbContextOptions<MySqlContext> options)
                : base(options)
        {
        } 

        public DbSet<Class> Class { get; set; }

    }
}

3、IBaseRepository.cs

using System;
using System.Linq;
using System.Linq.Expressions;

namespace  IRepository
{
    public interface IBaseRepository<T, TKey> : IDisposable where T : class
    { 
        T Find(TKey id); 
        T Find(Expression<Func<T, bool>> wherelamb); 
        void Add(T entity, bool isSaveChage = true);
        bool Update(T entity, bool isSaveChage = true);
        bool Delete(T entity, bool isSaveChage = true);
        int Delete(params int[] ids);
        IQueryable<T> LoadEntities(Expression<Func<T, bool>> whereLambda);
        IQueryable<T> LoadPageEntities<S>(int pageSize, int pageIndex, out int total, Expression<Func<T, bool>> whereLambda, Expression<Func<T, S>> orderbyLambda, bool isAsc);
        int SaveChange();
       
    }
}

4、IClassRepository.cs

using  Model;

namespace  IRepository
{
    public interface IClassRepository : IBaseRepository<Class, int>
    {
    }
}

5、IBaseService.cs

using  IRepository;

namespace  IService
{
    public interface IBaseService<T, TKey> : IBaseRepository<T, TKey> where T : class
    {

    }
}

6、IClassService.cs

using  Model;
using System;

namespace  IService
{
    public interface IClassService : IBaseService<Class, int>
    {
    }
}

7、BaseRepository.cs

using  DbFactory;
using  IRepository;
using Microsoft.EntityFrameworkCore;
using System;
using System.Linq;
using System.Linq.Expressions;

namespace  Repository
{
    public class BaseRepository<T, TKey> : IBaseRepository<T, TKey> where T : class
    {
        private MySqlContext _context;

        protected bool disposedValue;

        public BaseRepository(MySqlContext context)
        {
            _context = context;

        }  
        public T Find(TKey id)
        {
            return _context.Set<T>().Find(id);
        }

        public T Find(Expression<Func<T, bool>> wherelamb)
        {
            return _context.Set<T>().AsNoTracking().FirstOrDefault();
        }

        public virtual bool Update(T entity, bool isSaveChage = true)
        {
            _context.Entry(entity).State = EntityState.Modified;
            if (isSaveChage)
            {
                SaveChange();
            }
            return true;
        }

        public virtual bool Delete(T entity, bool isSaveChage = true)
        {
            _context.Entry(entity).State = EntityState.Deleted;
            if (isSaveChage)
            {
                SaveChange();
            }
            return true;

        }

        public virtual int Delete(params int[] ids)
        {
            foreach (var item in ids)
            {
                var entity = _context.Set<T>().Find(item);
                _context.Set<T>().Remove(entity);
            }
            SaveChange();
            return ids.Count();
        }

        public IQueryable<T> LoadEntities(Expression<Func<T, bool>> whereLambda)
        {
            return _context.Set<T>().Where(whereLambda).AsQueryable();
        }

        public IQueryable<T> LoadPageEntities<S>(int pageSize, int pageIndex, out int total, Expression<Func<T, bool>> whereLambda, Expression<Func<T, S>> orderbyLambda, bool isAsc)
        {
            total = _context.Set<T>().Where(whereLambda).Count();
            if (isAsc)
            {
                return
                _context.Set<T>()
                  .Where(whereLambda)
                  .OrderBy(orderbyLambda)
                  .Skip(pageSize * (pageIndex - 1))
                  .Take(pageSize)
                  .AsQueryable();
            }
            else
            {
                return
               _context.Set<T>()
                 .Where(whereLambda)
                 .OrderByDescending(orderbyLambda)
                 .Skip(pageSize * (pageIndex - 1))
                 .Take(pageSize)
                 .AsQueryable();
            }
        }

        protected virtual void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                if (disposing)
                {
                    _context?.Dispose();
                }
                disposedValue = true;
            }
        }
 
        public void Dispose()
        {
            Dispose(true);
        }

        public void Add(T entity, bool isSaveChage = true)
        {
            _context.Set<T>().Add(entity);
            if (isSaveChage)
            {
                SaveChange();
            }
        }

        public int SaveChange()
        {
            return _context.SaveChanges();
        }
    }
}

8、ClassRepository

using  DbFactory;
using  IRepository;
using  Model;

namespace  Repository
{
    public class ClassRepository : BaseRepository<Class, int>, IClassRepository
    {
        private MySqlContext _context;
        public ClassRepository(MySqlContext Dbcontext) : base(Dbcontext)
        {
            _context = Dbcontext;
        }
         
    }
}

9、BaseService

using  IRepository;
using  IService;
using System;
using System.Linq;
using System.Linq.Expressions;

namespace  Service
{
    public class BaseService<T, TKey> : IBaseService<T, TKey> where T : class
    {
        private readonly IBaseRepository<T, TKey> _repository;
        public BaseService(IBaseRepository<T, TKey> repository)
        {
            _repository = repository;
        }


        public T Find(TKey id)
        {
            return _repository.Find(id);
        }

        public T Find(Expression<Func<T, bool>> wherelamb)
        {
            return _repository.Find(wherelamb);
        }

        public IQueryable<T> LoadEntities(Expression<Func<T, bool>> whereLambda)
        {
            return _repository.LoadEntities(whereLambda);
        }

        public IQueryable<T> LoadPageEntities<S>(int pageSize, int pageIndex, out int total, Expression<Func<T, bool>> whereLambda, Expression<Func<T, S>> orderbyLambda, bool isAsc)
        {
            return _repository.LoadPageEntities(pageSize, pageIndex, out total, whereLambda, orderbyLambda, isAsc);
        }

        public int SaveChange()
        {
            return _repository.SaveChange();
        }

        public bool Update(T entity, bool isSaveChage = true)
        {
            return _repository.Update(entity, isSaveChage);
        }

        public void Add(T entity, bool isSaveChage = true)
        {
            _repository.Add(entity, isSaveChage = true);
        }
        public bool Delete(T entity, bool isSaveChage = true)
        {
            return _repository.Delete(entity, isSaveChage);
        }

        public int Delete(params int[] ids)
        {
            return _repository.Delete(ids);
        }
        public void Dispose()
        {
            _repository.Dispose();
        }
    }
}

10、ClassService

using  IRepository;
using  IService;
using  Model;

namespace  Service
{
    public class ClassService : BaseService<Class, int>, IClassService
    {
        private readonly IClassRepository _repository;
        public ClassService(IClassRepository repository) : base(repository)
        {
            _repository = repository;
        }

    }
}

11、DBExtensions

using  DbFactory;
using  Repository;
using Autofac;
using Autofac.Extensions.DependencyInjection;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;

namespace  Service
{
    public static class DBExtensions
    { 
        public static IHostBuilder UseMySql(this IHostBuilder hostBuilder, string connectionString = "")
        {
            try
            {
                if (string.IsNullOrEmpty(connectionString))
                {
                    //TODO:连接字符串从Zookeeper
                    //connectionString = Core.Configs.Get<string>("Connection.MySql");
                    connectionString = "Server=192.168.1.179;User ID=root;Password=root;Database=db1;";
                } 
                return hostBuilder.UseServiceProviderFactory(new AutofacServiceProviderFactory())
                    .ConfigureServices((ctx, services) =>  
                    { 
                        services.AddDbContext<MySqlContext>(options => options.UseMySql(connectionString, b => b.MigrationsAssembly("Test")));
                         
                    })
                    .ConfigureContainer<ContainerBuilder>((context, builder) =>
                    {
                        builder.RegisterAssemblyTypes(typeof(BaseRepository<,>).Assembly)
                              .Where(t => t.Name.EndsWith("Repository"))
                          .AsImplementedInterfaces();
                        builder.RegisterAssemblyTypes(typeof(BaseService<,>).Assembly)
                              .Where(t => t.Name.EndsWith("Service"))
                          .AsImplementedInterfaces();
                    });
            }
            catch (System.Exception ex)
            {

                throw;
            }
           
        }
        public static IServiceProvider UseMySql(this IServiceCollection services, string connectionString = "")
        {
            if (string.IsNullOrEmpty(connectionString))
            {
                //TODO:连接字符串从Zookeeper
                //connectionString = Core.Configs.Get<string>("Connection.MySql");
            }
            connectionString = "Server=192.168.1.179;User ID=root;Password=root;Database=db1;";

            services.AddDbContext<MySqlContext>(options =>
             options.UseMySql(connectionString, b => b.MigrationsAssembly("Test")));

            var builder = new ContainerBuilder();

            builder.Populate(services);
            builder.RegisterAssemblyTypes(typeof(BaseRepository<,>).Assembly)
                      .Where(t => t.Name.EndsWith("Repository"))
                  .AsImplementedInterfaces();
            builder.RegisterAssemblyTypes(typeof(BaseService<,>).Assembly)
                      .Where(t => t.Name.EndsWith("Service"))
                  .AsImplementedInterfaces();

            return new AutofacServiceProvider(builder.Build());
        }
    }
}

2、调用

控制台

新建控制台程序TestConsoleApp

1、Program

using  Service;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;

namespace TestConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");

            CreateDefaultHost(args).Build().Run();
        }
        static IHostBuilder CreateDefaultHost(string[] args) => new HostBuilder()
             .ConfigureServices((ctx, services) =>
             {
                 services.AddHostedService<TestService>(); 
             })
            .UseMySql(); //就这样引用一下就好了
    } 
}

2、TestService

using  IService;
using Microsoft.Extensions.Hosting;
using System;
using System.Threading;
using System.Threading.Tasks;

namespace TestConsoleApp
{

    internal class TestService : IHostedService, IDisposable
    {

        IClassService _classService;
        public TestService(IClassService classService)
        {
            _classService = classService;
        }
      
        private Timer _timer;
      
        public Task StartAsync(CancellationToken cancellationToken)
        {
            Console.WriteLine("starting.");
           
            _timer = new Timer(DoWork, null, TimeSpan.Zero,
                TimeSpan.FromSeconds(5));

            return Task.CompletedTask;
        }
        
        private void DoWork(object state)
        {
            Console.WriteLine("-------------------------------");
            var s = _classService.Find(x => true).Id;
            Console.WriteLine(s); 
            Console.WriteLine("working."); 
        }
         
        public void Dispose()
        {
            _timer?.Dispose();
        }

        public Task StopAsync(CancellationToken cancellationToken) => throw new NotImplementedException();
    }
}

3、RUN

每5秒就会查询一次。

.NETCore+EF+MySql+Autofac简单三层架构

WEB

这里就不演示了,这样services.UseMySql()就可以了。

using Service;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;

.NETCore+EF+MySql+Autofac简单三层架构

重点

那就是DBExtensions

关于Autofac的使用,网上大多都是这样的。

.NETCore+EF+MySql+Autofac简单三层架构

但是我要使用IHostBuilder的扩展。改成这样就好了。

.NETCore+EF+MySql+Autofac简单三层架构

上一篇:ASP.NET MVC IOC依赖注入之Autofac系列开篇


下一篇:c# – 在Owin Startup上解析InstancePerLifetimeScope中的Autofac服务