隐藏

.Net Core2.2 + EF Core + DI,三层框架项目搭建教程

发布:2021/12/30 17:30:41作者:管理员 来源:本站 浏览次数:919



笔记:


近两年.Net Core发展的很快,目前最新版为3.0预览版,之前在网上买了一本1.1版书籍都还没来得及看呢,估计现在拿出来看也毫无意义了。已多年.net工作经验,看书不如直接实际上手来得快,遇到问题再度娘吧。正好最近公司不忙时,抽空亲手搭建.Net Core项目熟悉一下,说起.net那最自豪的就是VS编译器了,强大的辅助功能很多中小型项目只需要下一步就可以创建完成。这里我们还需要简单封装一下,使用仓储模式对数据访问层封装和Service层封装,通过.net自带DI依赖注入进行创建对象。对于初学者的我只能简单的封装一下,接下来我会一一讲解框架的思路,如有更好的方案或不明的地方欢迎留言。转载请备注来源:https://www.cnblogs.com/han1982/p/11058788.html


下面是已搭建好的框架结构:




第一步:创建解决方案


使用Visual Studio 2019编译器创建解决方案,默认安装vs2019自带的.NET Core 2.1,创建.NET Core 2.2版需要下载SDK安装。


https://dotnet.microsoft.com/download/visual-studio-sdks?utm_source=getdotnetsdk&utm_medium=referral


接下来可以创建项目了,首先创建的是数据访问层,我们命名为common.Core,另外给他创建一个接口层common.Interface。




(注意所有程序集创建必须为.Net Core版,为以后发布垮平台考虑)


第二步:创建Model层


封装仓储层之前先来创建数据Model层,Nuget添加EF Core相关引用,工具 - NuGet包管理器 - 程序包管理器控制台,默认项目选择Model程序集依次安装以下组件包。


Install-Package Microsoft.EntityFrameworkCore -version 2.2.4


Install-Package Microsoft.EntityFrameworkCore.SqlServer -version 2.2.4


Install-Package Microsoft.EntityFrameworkCore.Tools -version 2.2.4


也可以在项目中找到依赖项,右键管理NuGet管理包方式进行添加。




Microsoft.EntityFrameworkCore.Tools中包含了Microsoft.EntityFrameworkCore.Design依赖包,不需要单独安装了。


这里我使用的是Database First模式,使用工具Scaffold-DbContext(数据库上下文脚手架)来生成model类文件和DbContext。


执行以下命令:-o (OutputDir) 指定用于输出类的目录  -f (Force) 生成时覆盖现有文件 -Context 指定生成的DbContext类的名称,省略的话按数据库名称生成DbContext类文件。


Scaffold-DbContext "server=.;database=ConCard;uid=sa;pwd=123123;" Microsoft.EntityFrameworkCore.SqlServer -O Models -F


出现错误:VS2019有个小小BUG,默认项目选中以后最终执行的不是被选中程序集,这里需要把model程序集设为启动项目,再次执行。


自动生成所有类模型文件,ConCardContext.cs数据库上下文也都帮你创建好了,这样就省去了我们手动写DBSet时间。


第三步:封装数据访问层


数据访问层主要封装仓储Repository和工作单元UnitOfWork,我把这两个合并到一个类中实现,通过简单工厂方式创建实例对象。


我们直接把ConCardContext.cs这个类复制到common.Core程序集中,把命名空间修改为common.Core。


这时应该报错,因为common.Core项目中没有引用EFCore依赖包,按之前Model层添加一样,使用Install-Package命令为common.Core添加依赖包,Tools可以不用安装。


依赖项中,右键添加引用,把Model和common.Interface项目引用,ConCardContext.cs中using model就不会报错了。


接下来修改下ConCardContext:


重写SaveChanges()方法


public override int SaveChanges()

{

   return base.SaveChanges(true);

}


删除OnConfiguring()方法,因为我们不需要在这里配置数据库连接,后面通过读取配置方式设置。

复制代码


protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)

{

   if (!optionsBuilder.IsConfigured)

   {

       optionsBuilder.UseSqlServer("server=.;database=ConCard;uid=sa;pwd=123123;");

    }

}


复制代码


common.Interface程序集中创建IconcardContext接口,ConCardContext类中继承自这个接口。(主要用来后期使用DI依赖注入使用,不用接口也可以用DbContext代替)


ConCardContext类:

复制代码


using System;

using com.Synjones.Model.Models;

using common.Interface;

using Microsoft.EntityFrameworkCore;

using Microsoft.EntityFrameworkCore.Metadata;


namespace common.Core

{

   public partial class ConCardContext : DbContext, IconcardContext

   {

       public ConCardContext()

       {

       }


       public ConCardContext(DbContextOptions<ConCardContext> options)

           : base(options)

       {

       }


       public override int SaveChanges()

       {

           return base.SaveChanges(true);

       }


       public virtual DbSet<Admin> Admin { get; set; }

       public virtual DbSet<User> User { get; set; }



       protected override void OnModelCreating(ModelBuilder modelBuilder)

       {

           modelBuilder.HasAnnotation("ProductVersion", "2.2.4-servicing-10062");


           modelBuilder.Entity<Admin>(entity =>

           {

               entity.Property(e => e.PassWord).HasMaxLength(50);


               entity.Property(e => e.UserId).HasMaxLength(50);

           });


           modelBuilder.Entity<User>(entity =>

           {

               entity.Property(e => e.Name).HasMaxLength(50);


               entity.Property(e => e.Phone).HasMaxLength(50);

           });

       }

   }

}


复制代码


开始继续创建Repository.cs仓储类,它是一个泛型类,并且拥有一个带有参数的构造方法,通过构造方法获得当前DbContext上下文对象,泛型类为指定Model类型,通过DbContext.Set<T>()方法最终得到相应的DbSet<T>对象来操作工作单元。


当然我们也要给他定义一个接口IRepository接口:

复制代码


using System;

using System.Collections.Generic;

using System.Data;

using System.Linq;

using System.Linq.Expressions;

using System.Text;


namespace common.Interface

{

   public interface IRepository<T> : IDisposable where T : class

   {

       /// <summary>

       /// 显式开启数据上下文事务

       /// </summary>

       /// <param name="isolationLevel">指定连接的事务锁定行为</param>

       void BeginTransaction(IsolationLevel isolationLevel = IsolationLevel.Unspecified);


       /// <summary>

       /// 提交事务的更改

       /// </summary>

       void Commit();


       /// <summary>

       /// 显式回滚事务,仅在显式开启事务后有用

       /// </summary>

       void Rollback();


       /// <summary>

       /// 提交当前单元操作的更改

       /// </summary>

       int SaveChanges();


       /// <summary>

       /// 获取 当前实体类型的查询数据集,数据将使用不跟踪变化的方式来查询,当数据用于展现时,推荐使用此数据集,如果用于新增,更新,删除时,请使用<see cref="TrackEntities"/>数据集

       /// </summary>

       IQueryable<T> Entities { get; }


       /// <summary>

       /// 获取 当前实体类型的查询数据集,当数据用于新增,更新,删除时,使用此数据集,如果数据用于展现,推荐使用<see cref="Entities"/>数据集

       /// </summary>

       IQueryable<T> TrackEntities { get; }


       /// <summary>

       /// 插入 - 通过实体对象添加

       /// </summary>

       /// <param name="entity">实体对象</param>

       /// <param name="isSave">是否执行</param>

       /// /// <returns></returns>

       T Add(T entity, bool isSave = true);


       /// <summary>

       /// 批量插入 - 通过实体对象集合添加

       /// </summary>

       /// <param name="entitys">实体对象集合</param>

       /// <param name="isSave">是否执行</param>

       void AddRange(IEnumerable<T> entitys, bool isSave = true);


       /// <summary>

       /// 删除 - 通过实体对象删除

       /// </summary>

       /// <param name="entity">实体对象</param>

       /// <param name="isSave">是否执行</param>

       void Delete(T entity, bool isSave = true);


       /// <summary>

       /// 批量删除 - 通过实体对象集合删除

       /// </summary>

       /// <param name="entitys">实体对象集合</param>

       /// <param name="isSave">是否执行</param>

       void Delete(bool isSave = false, params T[] entitys);


       /// <summary>

       /// 删除 - 通过主键ID删除

       /// </summary>

       /// <param name="id">主键ID</param>

       /// <param name="isSave">是否执行</param>

       void Delete(object id, bool isSave = true);


       /// <summary>

       /// 批量删除 - 通过条件删除

       /// </summary>

       /// <param name="where">过滤条件</param>

       /// <param name="isSave">是否执行</param>

       void Delete(Expression<Func<T, bool>> @where, bool isSave = true);


       /// <summary>

       /// 修改 - 通过实体对象修改

       /// </summary>

       /// <param name="entity">实体对象</param>

       /// <param name="isSave"></param>

       void Update(T entity, bool isSave = true);


       /// <summary>

       /// 批量修改 - 通过实体对象集合修改

       /// </summary>

       /// <param name="entitys">实体对象集合</param>

       /// <param name="isSave"></param>

       void Update(bool isSave = true, params T[] entitys);


       /// <summary>

       /// 是否满足条件

       /// </summary>

       /// <param name="where">过滤条件</param>

       /// <returns></returns>

       bool Any(Expression<Func<T, bool>> @where);


       /// <summary>

       /// 返回总条数

       /// </summary>

       /// <returns></returns>

       int Count();


       /// <summary>

       /// 返回总条数 - 通过条件过滤

       /// </summary>

       /// <param name="where">过滤条件</param>

       /// <returns></returns>

       int Count(Expression<Func<T, bool>> @where);


       /// <summary>

       /// 返回第一条记录

       /// </summary>

       /// <param name="where">过滤条件</param>

       /// <returns></returns>

       T FirstOrDefault(Expression<Func<T, bool>> @where);


       /// <summary>

       /// 返回第一条记录 - 通过条件过滤

       /// </summary>

       /// <typeparam name="TOrder">排序约束</typeparam>

       /// <param name="where">过滤条件</param>

       /// <param name="order">排序条件</param>

       /// <param name="isDesc">排序方式</param>

       /// <returns></returns>

       T FirstOrDefault<TOrder>(Expression<Func<T, bool>> @where, Expression<Func<T, TOrder>> order, bool isDesc = false);


       /// <summary>

       /// 去重查询

       /// </summary>

       /// <param name="where">过滤条件</param>

       /// <returns></returns>

       IQueryable<T> Distinct(Expression<Func<T, bool>> @where);


       /// <summary>

       /// 条件查询

       /// </summary>

       /// <param name="where">过滤条件</param>

       /// <returns></returns>

       IQueryable<T> Where(Expression<Func<T, bool>> @where);


       /// <summary>

       /// 条件查询 - 支持排序

       /// </summary>

       /// <typeparam name="TOrder">排序约束</typeparam>

       /// <param name="where">过滤条件</param>

       /// <param name="order">排序条件</param>

       /// <param name="isDesc">排序方式</param>

       /// <returns></returns>

       IQueryable<T> Where<TOrder>(Expression<Func<T, bool>> @where, Expression<Func<T, TOrder>> order, bool isDesc = false);


       /// <summary>

       /// 条件分页查询 - 支持排序

       /// </summary>

       /// <typeparam name="TOrder">排序约束</typeparam>

       /// <param name="where">过滤条件</param>

       /// <param name="order">排序条件</param>

       /// <param name="pageIndex">当前页码</param>

       /// <param name="pageSize">每页记录条数</param>

       /// <param name="count">返回总条数</param>

       /// <param name="isDesc">是否倒序</param>

       /// <returns></returns>

       IEnumerable<T> Where<TOrder>(Func<T, bool> @where, Func<T, TOrder> order, int pageIndex, int pageSize, out int count, bool isDesc = false);


       /// <summary>

       /// 条件分页查询 - 支持排序 - 支持Select导航属性查询

       /// </summary>

       /// <typeparam name="TOrder">排序约束</typeparam>

       /// <param name="where">过滤条件</param>

       /// <param name="order">排序条件</param>

       /// <param name="pageIndex">当前页码</param>

       /// <param name="pageSize">每页记录条数</param>

       /// <param name="count">返回总条数</param>

       /// <param name="isDesc">是否倒序</param>

       /// <returns></returns>

       IQueryable<T> Where<TOrder>(Expression<Func<T, bool>> @where, Expression<Func<T, TOrder>> order, int pageIndex, int pageSize, out int count, bool isDesc = false);


       /// <summary>

       /// 获取所有数据

       /// </summary>

       /// <returns></returns>

       IQueryable<T> GetAll();


       /// <summary>

       /// 获取所有数据 - 支持排序

       /// </summary>

       /// <typeparam name="TOrder">排序约束</typeparam>

       /// <param name="order">排序条件</param>

       /// <param name="isDesc">排序方式</param>

       /// <returns></returns>

       IQueryable<T> GetAll<TOrder>(Expression<Func<T, TOrder>> order, bool isDesc = false);


       /// <summary>

       /// 根据ID查询

       /// </summary>

       /// <typeparam name="Ttype">字段类型</typeparam>

       /// <param name="id">主键ID</param>

       /// <returns></returns>

       T GetById<Ttype>(Ttype id);


       /// <summary>

       /// 获取最大值

       /// </summary>

       /// <typeparam name="Ttype">字段类型</typeparam>

       /// <param name="column">字段条件</param>

       /// <returns></returns>

       Ttype Max<Ttype>(Expression<Func<T, Ttype>> column);


       /// <summary>

       /// 获取最大值

       /// </summary>

       /// <typeparam name="Ttype">字段类型</typeparam>

       /// <param name="column">字段条件</param>

       /// <param name="where">过滤条件</param>

       /// <returns></returns>

       Ttype Max<Ttype>(Expression<Func<T, Ttype>> column, Expression<Func<T, bool>> @where);


       /// <summary>

       /// 获取最小值

       /// </summary>

       /// <typeparam name="Ttype">字段类型</typeparam>

       /// <param name="column">字段条件</param>

       /// <returns></returns>

       Ttype Min<Ttype>(Expression<Func<T, Ttype>> column);


       /// <summary>

       /// 获取最小值

       /// </summary>

       /// <typeparam name="Ttype">字段类型</typeparam>

       /// <param name="column">字段条件</param>

       /// <param name="where">过滤条件</param>

       /// <returns></returns>

       Ttype Min<Ttype>(Expression<Func<T, Ttype>> column, Expression<Func<T, bool>> @where);


       /// <summary>

       /// 获取总数

       /// </summary>

       /// <typeparam name="TType">字段类型</typeparam>

       /// <param name="selector">字段条件</param>

       /// <param name="where">过滤条件</param>

       /// <returns></returns>

       TType Sum<TType>(Expression<Func<T, TType>> selector, Expression<Func<T, bool>> @where) where TType : new();

   }

}


复制代码


Repository类,实现了CRUD基本功能的封装:

复制代码


using common.Interface;

using Microsoft.EntityFrameworkCore;

using System;

using System.Collections.Generic;

using System.Data;

using System.Data.SqlClient;

using System.Linq;

using System.Linq.Expressions;

using System.Text;


namespace common.Core

{

   public class Repository<T> : IRepository<T> where T : class

   {

       private ConCardContext _dbContext;

       private readonly DbSet<T> _dbSet;

       private readonly string _connStr;


       public Repository(IconcardContext mydbcontext)

       {

           this._dbContext = mydbcontext as ConCardContext;

           this._dbSet = _dbContext.Set<T>();

           this._connStr = _dbContext.Database.GetDbConnection().ConnectionString;

       }


       public void BeginTransaction(IsolationLevel isolationLevel = IsolationLevel.Unspecified)

       {

           if (this._dbContext.Database.CurrentTransaction == null)

           {

               this._dbContext.Database.BeginTransaction(isolationLevel);

           }

       }


       public void Commit()

       {

           var transaction = this._dbContext.Database.CurrentTransaction;

           if (transaction != null)

           {

               try

               {

                   transaction.Commit();

               }

               catch (Exception)

               {

                   transaction.Rollback();

                   throw;

               }

           }

       }


       public void Rollback()

       {

           if (this._dbContext.Database.CurrentTransaction != null)

           {

               this._dbContext.Database.CurrentTransaction.Rollback();

           }

       }


       public int SaveChanges()

       {

           return this._dbContext.SaveChanges();

       }



       public IQueryable<T> Entities

       {

           get { return this._dbSet.AsNoTracking(); }

       }


       public IQueryable<T> TrackEntities

       {

           get { return this._dbSet; }

       }


       public T Add(T entity, bool isSave = true)

       {

           this._dbSet.Add(entity);

           if (isSave)

           {

               this.SaveChanges();

           }

           return entity;

       }


       public void AddRange(IEnumerable<T> entitys, bool isSave = true)

       {

           this._dbSet.AddRange(entitys);

           if (isSave)

           {

               this.SaveChanges();

           }

       }


       public void Delete(T entity, bool isSave = true)

       {

           this._dbSet.Remove(entity);

           if (isSave)

           {

               this.SaveChanges();

           }

       }


       public void Delete(bool isSave = true, params T[] entitys)

       {

           this._dbSet.RemoveRange(entitys);

           if (isSave)

           {

               this.SaveChanges();

           }

       }


       public void Delete(object id, bool isSave = true)

       {

           this._dbSet.Remove(this._dbSet.Find(id));

           if (isSave)

           {

               this.SaveChanges();

           }

       }


       public void Delete(Expression<Func<T, bool>> @where, bool isSave = true)

       {

           T[] entitys = this._dbSet.Where<T>(@where).ToArray();

           if (entitys.Length > 0)

           {

               this._dbSet.RemoveRange(entitys);

           }

           if (isSave)

           {

               this.SaveChanges();

           }

       }


       public void Update(T entity, bool isSave = true)

       {

           var entry = this._dbContext.Entry(entity);

           if (entry.State == EntityState.Detached)

           {

               entry.State = EntityState.Modified;

           }

           if (isSave)

           {

               this.SaveChanges();

           }

       }


       public void Update(bool isSave = true, params T[] entitys)

       {

           var entry = this._dbContext.Entry(entitys);

           if (entry.State == EntityState.Detached)

           {

               entry.State = EntityState.Modified;

           }

           if (isSave)

           {

               this.SaveChanges();

           }

       }


       public bool Any(Expression<Func<T, bool>> @where)

       {

           return this._dbSet.AsNoTracking().Any(@where);

       }


       public int Count()

       {

           return this._dbSet.AsNoTracking().Count();

       }


       public int Count(Expression<Func<T, bool>> @where)

       {

           return this._dbSet.AsNoTracking().Count(@where);

       }


       public T FirstOrDefault(Expression<Func<T, bool>> @where)

       {

           return this._dbSet.AsNoTracking().FirstOrDefault(@where);

       }


       public T FirstOrDefault<TOrder>(Expression<Func<T, bool>> @where, Expression<Func<T, TOrder>> order, bool isDesc = false)

       {

           if (isDesc)

           {

               return this._dbSet.AsNoTracking().OrderByDescending(order).FirstOrDefault(@where);

           }

           else

           {

               return this._dbSet.AsNoTracking().OrderBy(order).FirstOrDefault(@where);

           }

       }


       public IQueryable<T> Distinct(Expression<Func<T, bool>> @where)

       {

           return this._dbSet.AsNoTracking().Where(@where).Distinct();

       }


       public IQueryable<T> Where(Expression<Func<T, bool>> @where)

       {

           return this._dbSet.Where(@where);

       }


       public IQueryable<T> Where<TOrder>(Expression<Func<T, bool>> @where, Expression<Func<T, TOrder>> order, bool isDesc = false)

       {

           if (isDesc)

           {

               return this._dbSet.Where(@where).OrderByDescending(order);

           }

           else

           {

               return this._dbSet.Where(@where).OrderBy(order);

           }

       }


       public IEnumerable<T> Where<TOrder>(Func<T, bool> @where, Func<T, TOrder> order, int pageIndex, int pageSize, out int count, bool isDesc = false)

       {

           count = Count();

           if (isDesc)

           {

               return this._dbSet.Where(@where).OrderByDescending(order).Skip((pageIndex - 1) * pageSize).Take(pageSize);

           }

           else

           {

               return this._dbSet.Where(@where).OrderBy(order).Skip((pageIndex - 1) * pageSize).Take(pageSize);

           }

       }


       public IQueryable<T> Where<TOrder>(Expression<Func<T, bool>> @where, Expression<Func<T, TOrder>> order, int pageIndex, int pageSize, out int count, bool isDesc = false)

       {

           count = Count();

           if (isDesc)

           {

               return this._dbSet.Where(@where).OrderByDescending(order).Skip((pageIndex - 1) * pageSize).Take(pageSize);

           }

           else

           {

               return this._dbSet.Where(@where).OrderBy(order).Skip((pageIndex - 1) * pageSize).Take(pageSize);

           }

       }


       public IQueryable<T> GetAll()

       {

           return this._dbSet.AsNoTracking();

       }


       public IQueryable<T> GetAll<TOrder>(Expression<Func<T, TOrder>> order, bool isDesc = false)

       {

           if (isDesc)

           {

               return this._dbSet.AsNoTracking().OrderByDescending(order);

           }

           else

           {

               return this._dbSet.AsNoTracking().OrderBy(order);

           }

       }


       public T GetById<Ttype>(Ttype id)

       {

           return this._dbSet.Find(id);

       }


       public Ttype Max<Ttype>(Expression<Func<T, Ttype>> column)

       {

           if (this._dbSet.AsNoTracking().Any())

           {

               return this._dbSet.AsNoTracking().Max<T, Ttype>(column);

           }

           return default(Ttype);

       }


       public Ttype Max<Ttype>(Expression<Func<T, Ttype>> column, Expression<Func<T, bool>> @where)

       {

           if (this._dbSet.AsNoTracking().Any(@where))

           {

               return this._dbSet.AsNoTracking().Where(@where).Max<T, Ttype>(column);

           }

           return default(Ttype);

       }


       public Ttype Min<Ttype>(Expression<Func<T, Ttype>> column)

       {

           if (this._dbSet.AsNoTracking().Any())

           {

               return this._dbSet.AsNoTracking().Min<T, Ttype>(column);

           }

           return default(Ttype);

       }


       public Ttype Min<Ttype>(Expression<Func<T, Ttype>> column, Expression<Func<T, bool>> @where)

       {

           if (this._dbSet.AsNoTracking().Any(@where))

           {

               return this._dbSet.AsNoTracking().Where(@where).Min<T, Ttype>(column);

           }

           return default(Ttype);

       }


       public TType Sum<TType>(Expression<Func<T, TType>> selector, Expression<Func<T, bool>> @where) where TType : new()

       {

           object result = 0;


           if (new TType().GetType() == typeof(decimal))

           {

               result = this._dbSet.AsNoTracking().Where(where).Sum(selector as Expression<Func<T, decimal>>);

           }

           if (new TType().GetType() == typeof(decimal?))

           {

               result = this._dbSet.AsNoTracking().Where(where).Sum(selector as Expression<Func<T, decimal?>>);

           }

           if (new TType().GetType() == typeof(double))

           {

               result = this._dbSet.AsNoTracking().Where(where).Sum(selector as Expression<Func<T, double>>);

           }

           if (new TType().GetType() == typeof(double?))

           {

               result = this._dbSet.AsNoTracking().Where(where).Sum(selector as Expression<Func<T, double?>>);

           }

           if (new TType().GetType() == typeof(float))

           {

               result = this._dbSet.AsNoTracking().Where(where).Sum(selector as Expression<Func<T, float>>);

           }

           if (new TType().GetType() == typeof(float?))

           {

               result = this._dbSet.AsNoTracking().Where(where).Sum(selector as Expression<Func<T, float?>>);

           }

           if (new TType().GetType() == typeof(int))

           {

               result = this._dbSet.AsNoTracking().Where(where).Sum(selector as Expression<Func<T, int>>);

           }

           if (new TType().GetType() == typeof(int?))

           {

               result = this._dbSet.AsNoTracking().Where(where).Sum(selector as Expression<Func<T, int?>>);

           }

           if (new TType().GetType() == typeof(long))

           {

               result = this._dbSet.AsNoTracking().Where(where).Sum(selector as Expression<Func<T, long>>);

           }

           if (new TType().GetType() == typeof(long?))

           {

               result = this._dbSet.AsNoTracking().Where(where).Sum(selector as Expression<Func<T, long?>>);

           }

           return (TType)result;

       }


       public void Dispose()

       {

           this._dbContext.Dispose();

       }

   }

}


复制代码


这样仓储模式就创建好了,接下来想办法通过DI创建实例,而不是直接在Service层new一个实例,但是Repository是泛型类,通过DI创建需要设置,所有不同model类都要声明一遍,这里只能使用简单工厂来处理下。


添加RepositoryFactory类和IRepositoryFactory接口,接口中定义IRepository<T> CreateRepository<T>(IconcardContext mydbcontext) where T : class; 通过实现CreateRepository方法来创建不同数据模型的工作单元。


IRepositoryFactory接口:

复制代码


using System;

using System.Collections.Generic;

using System.Text;


namespace common.Interface

{

   public interface IRepositoryFactory

   {

       IRepository<T> CreateRepository<T>(IconcardContext mydbcontext) where T : class;

   }

}


复制代码


RepositoryFactory类:

复制代码


using common.Interface;

using System;

using System.Collections.Generic;

using System.Text;


namespace common.Core

{

   public class RepositoryFactory : IRepositoryFactory

   {

       public IRepository<T> CreateRepository<T>(IconcardContext mydbcontext) where T : class

       {

           return new Repository<T>(mydbcontext);

       }

   }

}


复制代码




第四步:创建Service层:


老规矩,先添加新建项目Service和IService,一个是定义Service接口,另一个是它的实现,他们都需要引入Model层和Interface层,Service要引入IService层。


添加BaseService类和IBaseService接口,接口中定义IRepository<T> CreateService<T>() where T : class, new();


IBaseService接口:

复制代码


using common.Interface;

using System;

using System.Collections.Generic;

using System.Text;


namespace com.Synjones.IService

{

   public interface IBaseService

   {

       IRepository<T> CreateService<T>() where T : class, new();

   }

}


复制代码


BaseService类:

复制代码


using com.Synjones.IService;

using common.Interface;

using System;

using System.Collections.Generic;

using System.Text;


namespace com.Synjones.Service

{

   public class BaseService : IBaseService

   {

       private IRepositoryFactory _repositoryFactory;

       private IconcardContext _mydbcontext;

       public BaseService(IRepositoryFactory repositoryFactory, IconcardContext mydbcontext)

       {

           this._repositoryFactory = repositoryFactory;

           this._mydbcontext = mydbcontext;

       }


       public IRepository<T> CreateService<T>() where T : class, new()

       {

           return _repositoryFactory.CreateRepository<T>(_mydbcontext);

       }

   }

}


复制代码


这里说明一下,BaseService类也是泛型类,也不需要通过DI方式创建,Service层中根据每个模块添加一个Service类,并且继承BaseService类,DI依赖注入模块Service中直接获取到指定模型的仓储进行操作。


添加User模块UserService类和IUserService接口,UserService类继承父类BaseService,生成构造函数。


public UserService(IRepositoryFactory repositoryFactory, IconcardContext mydbcontext) : base(repositoryFactory, mydbcontext)

{

}


下面我们简单举例对user表读取操作的业务层实现,定义接口List<User> GetUsers(),实现GetUsers()方法,读取所有user表数据。


IUserService接口:

复制代码


using com.Synjones.Model.Models;

using System;

using System.Collections.Generic;

using System.Text;


namespace com.Synjones.IService

{

   public interface IUserService

   {

       List<User> GetUsers();

   }

}


复制代码


UserService类:

复制代码


using com.Synjones.IService;

using com.Synjones.Model.Models;

using common.Interface;

using System;

using System.Collections.Generic;

using System.Text;

using System.Linq;


namespace com.Synjones.Service

{

   public class UserService : BaseService, IUserService

   {

       public UserService(IRepositoryFactory repositoryFactory, IconcardContext mydbcontext) : base(repositoryFactory, mydbcontext)

       {

       }


       public List<User> GetUsers()

       {

           var service = this.CreateService<User>();

           return service.GetAll().ToList();

       }

   }

}


复制代码






第五步:UI创建并调用Service接口返回数据。


我这里创建了WebApi项目,依赖项中添加引用所有其他项目。


配置数据库连接字符串,打开appsettings.json,添加


"ConnectionStrings": {

   "SchoolConnection": "server=.;database=ConCard;uid=sa;pwd=123123;"

 }


配置EF服务注册:


打开Startup.cs,ConfigureServices方法中添加services.AddDbContext指定数据库连接配置项,通过services.AddScoped添加DI依赖注入配置。

复制代码


public void ConfigureServices(IServiceCollection services)

{

     services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

     // 配置EF服务注册

     services.AddDbContext<common.Core.ConCardContext>(options =>

     options.UseSqlServer(Configuration.GetConnectionString("SchoolConnection")));

     services.AddScoped<IconcardContext, common.Core.ConCardContext>();

     services.AddScoped<IRepositoryFactory, RepositoryFactory>();

     services.AddScoped<IUserService, UserService>();

}


复制代码


修改下ValuesController控制器,添加构造函数和Get方法。


WebApi项目设为启动项目,运行看结果。