笔记:

  近两年.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(); entity.Property(e => e.UserId).HasMaxLength();
}); modelBuilder.Entity<User>(entity =>
{
entity.Property(e => e.Name).HasMaxLength(); entity.Property(e => e.Phone).HasMaxLength();
});
}
}
}

开始继续创建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 > )
{
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 - ) * pageSize).Take(pageSize);
}
else
{
return this._dbSet.Where(@where).OrderBy(order).Skip((pageIndex - ) * 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 - ) * pageSize).Take(pageSize);
}
else
{
return this._dbSet.Where(@where).OrderBy(order).Skip((pageIndex - ) * 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 = ; 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项目设为启动项目,运行看结果。

.Net Core2.2 + EF Core + DI,三层框架项目搭建教程的更多相关文章

  1. Spring+SpringMvc+Mybatis框架集成搭建教程

    一.背景 最近有很多同学由于没有过SSM(Spring+SpringMvc+Mybatis , 以下简称SSM)框架的搭建的经历,所以在自己搭建SSM框架集成的时候,出现了这样或者那样的问题,很是苦恼 ...

  2. .net core2.1 - ef core数据库迁移,初始化种子数据

    起因:早上偶然看见一篇文章说是ef core(2.x)使用种子数据,主表子表迁移时候,正常情况下说是无法迁移成功,索性就试试,结果是和ef6的一样,没感觉有什么大的区别.一切OK,见下面内容. 1.首 ...

  3. ABP CORE 框架入门视频教程《电话薄》基于 Asp.NET Core2.0 EF Core

    ABP框架简介 ABP是"ASP.NET Boilerplate Project (ASP.NET样板项目)"的简称. ASP.NET Boilerplate是一个用最佳实践和流行 ...

  4. .Net框架搭建:SQL Server EF MVC简单三层框架

    https://blog.csdn.net/pukuimin1226/article/details/52313656

  5. EasyFastCMS系列教学课程——1、三层框架的搭建

    在本系列教程中,我们以一个大型CMS系统的完整开发流程为例,和大家一起探讨net开发的经验和教训.在本程序中,我们采用了流行的三层/N层框架+仓储模式的架构模式.项目分层示意图:     各层的主要用 ...

  6. 基于.Net Core的API框架的搭建(1)

    目标 我们的目标是要搭建一个API控制器的项目,API控制器提供业务服务. 一.开发框架搭建 1.开发前准备 开发前,我们需要下载如下软件,安装过程略: (1) 开发工具:VS2017 (2) 数据库 ...

  7. 基于.Net Core的API框架的搭建(4)

    6.加入日志功能 日志我们选用log4net,首先引入程序包: 选择2.0.8版本安装.然后在项目根目录新增log4net的配置文件log4net.config: <?xml version=& ...

  8. 基于.Net Core的API框架的搭建(2)

    4.加入数据库支持 下面我们为项目加入数据库支持,修改appsettings.json: 然后我们要生成实体类,打开VS工具->NuGet包管理器->程序包管理器控制台: 输入命令: Sc ...

  9. 基于.Net Core的API框架的搭建(3)

    5.加入缓存支持 我们希望为项目增加缓存支持,我们选择Redis做为缓存数据库. 首先,我们在Services目录增加一个缓存接口类ICacheService: using System; using ...

随机推荐

  1. POJ 2636:Electrical Outlets

    Electrical Outlets Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9597   Accepted: 718 ...

  2. BZOJ_3667_Rabin-Miller算法_Mille_Rabin+Pollard rho

    BZOJ_3667_Rabin-Miller算法_Mille_Rabin+Pollard rho Description Input 第一行:CAS,代表数据组数(不大于350),以下CAS行,每行一 ...

  3. flask核心对象Flask实例初探

    flask的核心程序就两个: werkzegu(WSGI)库,封装了http.web通信等最关键的wsgi功能②Jinja2是Python下一个被广泛应用的模版引擎,方便了html模板的创建和使用 而 ...

  4. 第十五周 Leetcode 517. Super Washing Machines(HARD) 贪心

    Leetcode517 很有趣的一道题 由于每一步可以任选某些数字对它们进行转移,所以实际上是在求最优解中的最复杂转移数. 那么我们考虑,到底哪一个位置要经过的流量最大呢? 枚举每个位置,考虑它左边的 ...

  5. linux下的C语言开发 GDB的例子

    在很多人的眼里,C语言和linux常常是分不开的.这其中的原因很多,其中最重要的一部分我认为是linux本身就是C语言的杰出作品.当然,linux操作系统本身对C语言的支持也是相当到位的.作为一个真正 ...

  6. C#面向过程之冒泡排序

    //定义一个数组,准备冒泡排序 ,,-,,,,-,}; //定义一个中间变量 ; //n个数字比较需要进行n-1次比较 ; j < arr.Length - - i; j++) { //每一趟的 ...

  7. mac+php+xdebug

    1,下载xdebug 2,进入xdebug-2.4.0RC4目录,运行phpize命令, 2,google之后说要安装autoconf brew install autoconf 3,但是使用brew ...

  8. bzoj 2200: [Usaco2011 Jan]道路和航线【spfa】

    直接跑最短路就行了--还不用判负环 #include<iostream> #include<cstdio> #include<queue> using namesp ...

  9. 测试神器Swagger的相关使用

    1.Swagger简介 swagger官网地址: https://swagger.io/ swagger官网文档介绍地址: https://swagger.io/about/ ​ swagge是一个易 ...

  10. Kafka详解与总结(六)

    索引 稀疏存储,每隔一定字节的数据建立一条索引(这样的目的是为了减少索引文件的大小). 下图为一个partition的索引示意图: 注: 现在对6.和8建立了索引,如果要查找7,则会先查找到8然后,再 ...