19

.Net Core2.2 + EF Core + DI,三层框架项目搭建教程 - 蚂蚁穿上铠甲手持宝剑

 4 years ago
source link: https://www.cnblogs.com/han1982/p/11058788.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

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

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

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

447901-20190620144557113-1239244524.png

第一步:创建解决方案

使用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。

 

447901-20190620154302586-803021187.png

(注意所有程序集创建必须为.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

447901-20190621095630004-1114095007.png

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

447901-20190621102833046-339254608.png

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

447901-20190621104440171-625340191.png

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

447901-20190621110832078-1010610532.png

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

第三步:封装数据访问层

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

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

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

447901-20190621112218787-165537154.png

依赖项中,右键添加引用,把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类:

ContractedBlock.gifExpandedBlockStart.gif

View Code

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

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

ContractedBlock.gifExpandedBlockStart.gif

View Code

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

ContractedBlock.gifExpandedBlockStart.gif

View Code

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

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

IRepositoryFactory接口:

ContractedBlock.gifExpandedBlockStart.gif

View Code

RepositoryFactory类:

ContractedBlock.gifExpandedBlockStart.gif

View Code

447901-20190621132311149-1771394238.png

 第四步:创建Service层:

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

447901-20190621134014408-13817944.png

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

IBaseService接口:

ContractedBlock.gifExpandedBlockStart.gif

View Code

BaseService类:

ContractedBlock.gifExpandedBlockStart.gif

View Code

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

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

447901-20190621140001137-538694621.png
public UserService(IRepositoryFactory repositoryFactory, IconcardContext mydbcontext) : base(repositoryFactory, mydbcontext)
{
}

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

IUserService接口:

ContractedBlock.gifExpandedBlockStart.gif

View Code

UserService类:

ContractedBlock.gifExpandedBlockStart.gif

View Code

 

447901-20190621143022247-706527359.png

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

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

447901-20190621144522259-844107574.png

配置数据库连接字符串,打开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方法。

447901-20190621150013288-966620046.png

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

 447901-20190621153541836-2096541499.png


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK