博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
.netCore+Vue 搭建的简捷开发框架 (2)--仓储层实现和EFCore 的使用
阅读量:5344 次
发布时间:2019-06-15

本文共 17094 字,大约阅读时间需要 56 分钟。

书接上文,继续搭建我们基于.netCore 的开发框架。首先是我们的项目分层结构。

 

这个分层结构,是参考张老师的分层结构,但是实际项目中,我没有去实现仓储模型。因为我使用的是EFCore ,最近也一直在想,EFCore 在我们的架构体系中到底扮演着什么样的角色??

当然,实现仓储层,也有他的好处,如果真的以后要更换ORM框架的时候,不用去更改服务层逻辑,不用直接在仓储里面做更改就可以了。但是对于小项目,可能运行个十年都不会换数据库,不会换ORM的项目,仓储层的意义在哪?

希望对此有自己想法的朋友一起讨论。在本系列里,我将保留仓储层。

上面的分层结构,很容易就搭建好了,但是基于.NetCore 的项目,可能最主要的一点就是如何利用好DI,怎么来实现依赖注入。

依照上图中的依赖关系,我们以此构建自己相应层级中的内容。

分别在IRepository和Repository项目下,新建Base文件夹,并分别建立IBaseRepository和BaseRepository

具体代码如下:

IBaseRepository.cs:

1 using Sincere.Core.Model; 2 using System; 3 using System.Collections.Generic; 4 using System.Data; 5 using System.Data.SqlClient; 6 using System.Linq.Expressions; 7 using System.Text; 8 using System.Threading.Tasks; 9 10 namespace Sincere.Core.IRepository.Base11 {12     public interface IBaseRepository
where TEntity : class13 {14 Task
Execute(string sql, List
parms, CommandType cmdType = CommandType.Text);15 Task
> Query(string sql, List
parms, CommandType cmdType = CommandType.Text);16 Task
Insert(TEntity model);17 Task
InsertRange(List
datas);18 19 Task
Del(TEntity model);20 21 Task
DelBy(Expression
> delWhere);22 23 Task
Modify(TEntity model);24 25 Task
Modify(TEntity model, params string[] propertyNames);26 27 Task
ModifyBy(TEntity model, Expression
> whereLambda, params string[] modifiedPropertyNames);28 29 Task
> GetList();30 31 Task
> GetListBy(Expression
> whereLambda);32 33 Task
GetModelById(Expression
> whereLambda);34 35 Task
> GetListBy
(Expression
> whereLambda, Expression
> orderLambda, bool isAsc = true);36 37 Task
> GetListBy
(int top, Expression
> whereLambda, Expression
> orderLambda, bool isAsc = true);38 39 Task
> GetListBy
(Expression
> whereLambda, Expression
> orderLambda1, Expression
> orderLambda2, bool isAsc1 = true, bool isAsc2 = true);40 41 Task
> GetListBy
(int top, Expression
> whereLambda, Expression
> orderLambda1, Expression
> orderLambda2, bool isAsc1 = true, bool isAsc2 = true);42 43 Task
> GetPagedList
(int pageIndex, int pageSize, Expression
> whereLambda, Expression
> orderByLambda, bool isAsc = true);44 45 Task
> GetPagedList
(Expression
> whereLambda, Expression
> orderByLambda, bool isAsc = true, int pageIndex = 1, int pageSize = 20);46 47 void RollBackChanges();48 49 }50 }
View Code

BaseRepository.cs:

1 using Microsoft.EntityFrameworkCore;  2 using Sincere.Core.IRepository.Base;  3 using Sincere.Core.Model;  4 using Sincere.Core.Model.Models;  5 using System;  6 using System.Collections.Generic;  7 using System.Data;  8 using System.Data.SqlClient;  9 using System.Linq; 10 using System.Linq.Expressions; 11 using System.Reflection; 12 using System.Text; 13 using System.Threading.Tasks; 14  15 namespace Sincere.Core.Repository.Base 16 { 17     public class BaseRepository
: IBaseRepository
where TEntity : class, new() 18 { 19 private BaseCoreContext _db; 20 private readonly DbSet
_dbSet; 21 22 internal BaseCoreContext Db 23 { 24 get { return _db; } 25 private set { _db = value; } 26 } 27 public BaseRepository(IBaseContext mydbcontext) 28 { 29 this._db = mydbcontext as BaseCoreContext; 30 this._dbSet = _db.Set
(); 31 } 32 33 #region INSERT 34 35 ///
36 /// 新增 实体 37 /// 38 ///
39 ///
40 //public async Task
Insert(TEntity model, bool isSaveChanges = false) 41 public async Task
Insert(TEntity model) 42 { 43 _db.Set
().Add(model); 44 //if (isSaveChanges) 45 //{ 46 return await _db.SaveChangesAsync() > 0; 47 //} 48 //else 49 //{ 50 // return false; 51 //} 52 53 } 54 55 ///
56 /// 普通批量插入 57 /// 58 ///
59 public async Task
InsertRange(List
datas) 60 { 61 await _db.Set
().AddRangeAsync(datas); 62 return await _db.SaveChangesAsync() == datas.Count; 63 } 64 65 #endregion INSERT 66 67 #region Delete 68 69 #region 2.0 根据id删除 + int Del(T model) 70 ///
71 /// 2.0 根据id删除 72 /// 73 ///
必须包含要删除id的对象 74 ///
75 public async Task
Del(TEntity model) 76 { 77 _db.Set
().Attach(model); 78 _db.Set
().Remove(model); 79 return await _db.SaveChangesAsync(); 80 } 81 #endregion 82 83 #region 2.1 根据条件删除 + int DelBy(Expression
> delWhere) 84 ///
85 /// 2.1 根据条件删除 86 /// 87 ///
88 ///
返回受影响的行数
89 public async Task
DelBy(Expression
> delWhere) 90 { 91 //2.1.1 查询要删除的数据 92 List
listDeleting = _db.Set
().Where(delWhere).ToList(); 93 //2.1.2 将要删除的数据 用删除方法添加到 EF 容器中 94 listDeleting.ForEach(u => 95 { 96 _db.Set
().Attach(u); //先附加到EF 容器 97 _db.Set
().Remove(u); //标识为删除状态 98 }); 99 //2.1.3 一次性生成sql语句 到数据库执行删除100 return await _db.SaveChangesAsync();101 }102 #endregion103 104 105 #endregion106 107 #region UPDATE108 109 #region 3.0 修改实体 + int Modify(T model)110 ///
111 /// 修改实体112 /// 113 ///
114 ///
115 public async Task
Modify(TEntity model)116 {117 //EntityEntry entry = _db.Entry
(model);118 _db.Set
().Update(model);119 return await _db.SaveChangesAsync();120 }121 #endregion122 123 #region 3.1 修改实体,可修改指定属性 + int Modify(T model, params string[] propertyNames)124 ///
125 /// 3.1 修改实体,可修改指定属性126 /// 127 ///
128 ///
129 ///
130 public async Task
Modify(TEntity model, params string[] propertyNames)131 {132 //3.1.1 将对象添加到EF中133 EntityEntry entry = _db.Entry
(model);134 //3.1.2 先设置对象的包装状态为 Unchanged135 entry.State = EntityState.Unchanged;136 //3.1.3 循环被修改的属性名数组137 foreach (string propertyName in propertyNames)138 {139 //将每个被修改的属性的状态设置为已修改状态;这样在后面生成的修改语句时,就只为标识为已修改的属性更新140 entry.Property(propertyName).IsModified = true;141 }142 return await _db.SaveChangesAsync();143 }144 #endregion145 146 #region 3.2 批量修改 + int ModifyBy(T model, Expression
> whereLambda, params string[] modifiedPropertyNames)147 ///
148 /// 3.2 批量修改149 /// 150 ///
151 ///
152 ///
153 ///
154 public async Task
ModifyBy(TEntity model, Expression
> whereLambda, params string[] modifiedPropertyNames)155 {156 //3.2.1 查询要修改的数据157 List
listModifing = _db.Set
().Where(whereLambda).ToList();158 //3.2.2 获取实体类类型对象159 Type t = typeof(TEntity);160 //3.2.3 获取实体类所有的公共属性161 List
propertyInfos = t.GetProperties(BindingFlags.Instance | BindingFlags.Public).ToList();162 //3.2.4 创建实体属性字典集合163 Dictionary
dicPropertys = new Dictionary
();164 //3.2.5 将实体属性中要修改的属性名 添加到字典集合中 键:属性名 值:属性对象165 propertyInfos.ForEach(p =>166 {167 if (modifiedPropertyNames.Contains(p.Name))168 {169 dicPropertys.Add(p.Name, p);170 }171 });172 //3.2.6 循环要修改的属性名173 foreach (string propertyName in modifiedPropertyNames)174 {175 //判断要修改的属性名是否在实体类的属性集合中存在176 if (dicPropertys.ContainsKey(propertyName))177 {178 //如果存在,则取出要修改的属性对象179 PropertyInfo proInfo = dicPropertys[propertyName];180 //取出要修改的值181 object newValue = proInfo.GetValue(model, null);182 //批量设置要修改对象的属性183 foreach (TEntity item in listModifing)184 {185 //为要修改的对象的要修改的属性设置新的值186 proInfo.SetValue(item, newValue, null);187 }188 }189 }190 //一次性生成sql语句 到数据库执行191 return await _db.SaveChangesAsync();192 }193 #endregion194 195 196 #endregion UPDATE197 198 #region SELECT199 200 #region 5.0 根据条件查询 + List
GetListBy(Expression
> whereLambda)201 ///
202 /// 5.0 根据条件查询203 /// 204 ///
205 ///
206 public async Task
> GetListBy(Expression
> whereLambda)207 {208 return await _db.Set
().Where(whereLambda).AsNoTracking().ToListAsync();209 }210 211 public async Task
GetModelById(Expression
> whereLambda)212 {213 return await _db.Set
().Where(whereLambda).AsNoTracking().FirstOrDefaultAsync();214 }215 public async Task
> GetList()216 {217 return await _db.Set
().AsNoTracking().ToListAsync();218 }219 #endregion220 221 #region 5.1 根据条件查询,并排序 + List
GetListBy
(Expression
> whereLambda, Expression
> orderLambda, bool isAsc = true)222 ///
223 /// 5.1 根据条件查询,并排序224 /// 225 ///
226 ///
227 ///
228 ///
229 ///
230 public async Task
> GetListBy
(Expression
> whereLambda, Expression
> orderLambda, bool isAsc = true)231 {232 if (isAsc)233 {234 return await _db.Set
().Where(whereLambda).OrderBy(orderLambda).AsNoTracking().ToListAsync();235 }236 else237 {238 return await _db.Set
().Where(whereLambda).OrderByDescending(orderLambda).AsNoTracking().ToListAsync();239 }240 }241 #endregion242 243 #region 5.2 根据条件查询Top多少个,并排序 + List
GetListBy
(int top, Expression
> whereLambda, Expression
> orderLambda, bool isAsc = true)244 ///
245 /// 5.2 根据条件查询Top多少个,并排序246 /// 247 ///
248 ///
249 ///
250 ///
251 ///
252 ///
253 public async Task
> GetListBy
(int top, Expression
> whereLambda, Expression
> orderLambda, bool isAsc = true)254 {255 if (isAsc)256 {257 return await _db.Set
().Where(whereLambda).OrderBy(orderLambda).Take(top).AsNoTracking().ToListAsync();258 }259 else260 {261 return await _db.Set
().Where(whereLambda).OrderByDescending(orderLambda).Take(top).AsNoTracking().ToListAsync();262 }263 }264 #endregion265 266 #region 5.3 根据条件排序查询 双排序 + List
GetListBy
(Expression
> whereLambda, Expression
> orderLambda1, Expression
> orderLambda2, bool isAsc1 = true, bool isAsc2 = true)267 ///
268 /// 5.3 根据条件排序查询 双排序269 /// 270 ///
271 ///
272 ///
273 ///
274 ///
275 ///
276 ///
277 ///
278 public async Task
> GetListBy
(Expression
> whereLambda, Expression
> orderLambda1, Expression
> orderLambda2, bool isAsc1 = true, bool isAsc2 = true)279 {280 if (isAsc1)281 {282 if (isAsc2)283 {284 return await _db.Set
().Where(whereLambda).OrderBy(orderLambda1).ThenBy(orderLambda2).AsNoTracking().ToListAsync();285 }286 else287 {288 return await _db.Set
().Where(whereLambda).OrderBy(orderLambda1).ThenByDescending(orderLambda2).AsNoTracking().ToListAsync();289 }290 }291 else292 {293 if (isAsc2)294 {295 return await _db.Set
().Where(whereLambda).OrderByDescending(orderLambda1).ThenBy(orderLambda2).AsNoTracking().ToListAsync();296 }297 else298 {299 return await _db.Set
().Where(whereLambda).OrderByDescending(orderLambda1).ThenByDescending(orderLambda2).AsNoTracking().ToListAsync();300 }301 }302 }303 #endregion304 305 #region 5.3 根据条件排序查询Top个数 双排序 + List
GetListBy
(int top, Expression
> whereLambda, System.Linq.Expressions.Expression
> orderLambda1, Expression
> orderLambda2, bool isAsc1 = true, bool isAsc2 = true)306 ///
307 /// 5.3 根据条件排序查询Top个数 双排序308 /// 309 ///
310 ///
311 ///
312 ///
313 ///
314 ///
315 ///
316 ///
317 ///
318 public async Task
> GetListBy
(int top, Expression
> whereLambda, Expression
> orderLambda1, Expression
> orderLambda2, bool isAsc1 = true, bool isAsc2 = true)319 {320 if (isAsc1)321 {322 if (isAsc2)323 {324 return await _db.Set
().Where(whereLambda).OrderBy(orderLambda1).ThenBy(orderLambda2).Take(top).AsNoTracking().ToListAsync();325 }326 else327 {328 return await _db.Set
().Where(whereLambda).OrderBy(orderLambda1).ThenByDescending(orderLambda2).Take(top).AsNoTracking().ToListAsync();329 }330 }331 else332 {333 if (isAsc2)334 {335 return await _db.Set
().Where(whereLambda).OrderByDescending(orderLambda1).ThenBy(orderLambda2).Take(top).AsNoTracking().ToListAsync();336 }337 else338 {339 return await _db.Set
().Where(whereLambda).OrderByDescending(orderLambda1).ThenByDescending(orderLambda2).Take(top).AsNoTracking().ToListAsync();340 }341 }342 }343 #endregion344 345 #endregion SELECT346 347 #region 分页348 349 #region 6.0 分页查询 + List
GetPagedList
350 ///
351 /// 分页查询 + List
GetPagedList352 ///
353 ///
354 ///
页码355 ///
页容量356 ///
条件 lambda表达式357 ///
排序 lambda表达式358 ///
359 public async Task
> GetPagedList
(int pageIndex, int pageSize, Expression
> whereLambda, Expression
> orderByLambda, bool isAsc = true)360 {361 // 分页 一定注意: Skip 之前一定要 OrderBy362 if (isAsc)363 {364 return await _db.Set
().Where(whereLambda).OrderBy(orderByLambda).Skip((pageIndex - 1) * pageSize).Take(pageSize).AsNoTracking().ToListAsync();365 }366 else367 {368 return await _db.Set
().Where(whereLambda).OrderByDescending(orderByLambda).Skip((pageIndex - 1) * pageSize).Take(pageSize).AsNoTracking().ToListAsync();369 }370 }371 #endregion372 373 #region 6.1分页查询 带输出 +List
GetPagedList
374 ///
375 /// 分页查询 带输出376 /// 377 ///
378 ///
379 ///
380 ///
381 ///
382 ///
383 ///
384 ///
385 public async Task
> GetPagedList
(Expression
> whereLambda, Expression
> orderByLambda, bool isAsc = true, int pageIndex = 1, int pageSize = 20)386 {387 var rowCount = await _db.Set
().Where(whereLambda).CountAsync();388 389 int pageCount = (Math.Ceiling(rowCount.ObjToDecimal() / pageSize.ObjToDecimal())).ObjToInt();390 391 List
list = null;392 393 if (isAsc)394 {395 list = await _db.Set
().OrderBy(orderByLambda).Where(whereLambda).Skip((pageIndex - 1) * pageSize).Take(pageSize).AsNoTracking().ToListAsync();396 }397 else398 {399 list = await _db.Set
().OrderByDescending(orderByLambda).Where(whereLambda).Skip((pageIndex - 1) * pageSize).Take(pageSize).AsNoTracking().ToListAsync();400 }401 402 return new PageModel
() { dataCount = rowCount, pageCount = pageCount, page = pageIndex, PageSize = pageSize, data = list };403 }404 #endregion405 406 #endregion407 408 #region ORTHER409 410 ///
411 /// 执行存储过程或自定义sql语句--返回集合412 /// 413 ///
414 ///
415 ///
416 ///
417 public async Task
> Query(string sql, List
parms, CommandType cmdType = CommandType.Text)418 {419 //存储过程(exec getActionUrlId @name,@ID)420 if (cmdType == CommandType.StoredProcedure)421 {422 StringBuilder paraNames = new StringBuilder();423 foreach (var sqlPara in parms)424 {425 paraNames.Append($" @{sqlPara},");426 }427 sql = paraNames.Length > 0 ? $"exec {sql} {paraNames.ToString().Trim(',')}" : $"exec {sql} ";428 }429 430 return await _db.Set
().FromSql(sql).ToListAsync();431 432 }433 434 435 ///
436 /// 回滚437 /// 438 public void RollBackChanges()439 {440 var items = _db.ChangeTracker.Entries().ToList();441 items.ForEach(o => o.State = EntityState.Unchanged);442 }443 444 ///
445 /// 自定义语句和存储过程的增删改--返回影响的行数446 /// 447 ///
448 ///
449 ///
450 ///
451 public async Task
Execute(string sql, List
parms, CommandType cmdType = CommandType.Text)452 {453 //存储过程(exec getActionUrlId @name,@ID)454 if (cmdType == CommandType.StoredProcedure)455 {456 StringBuilder paraNames = new StringBuilder();457 foreach (var sqlPara in parms)458 {459 paraNames.Append($" @{sqlPara},");460 }461 sql = paraNames.Length > 0 ?462 $"exec {sql} {paraNames.ToString().Trim(',')}" :463 $"exec {sql} ";464 }465 466 int ret = await _db.Database.ExecuteSqlCommandAsync(sql, parms.ToArray());467 return 0;468 }469 470 471 #endregion ORTHER472 }473 }
View Code

BaseRepository中主要是实现了一些基础的CURD操作,并且封装了一些常用的数据库操作。比如分页、执行sql语句等等

如果直接复制以上代码,会报错,因为你的项目中还没有数据上下文:

 下面就引入我们将要使用的ORM框架--EFCore

首先,在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

 

 此系类中我们采用databaseFrist的方式来生成Model文件和上下文。在数据库中先建用于测试的表--Advertisement

语句如下:

1 USE [BaseCore] 2 GO 3  4 /****** Object:  Table [dbo].[Advertisement]    Script Date: 08/28/2019 10:43:34 ******/ 5 SET ANSI_NULLS ON 6 GO 7  8 SET QUOTED_IDENTIFIER ON 9 GO10 11 CREATE TABLE [dbo].[Advertisement](12     [Id] [int] IDENTITY(1,1) NOT NULL,13     [Createdate] [datetime] NOT NULL,14     [ImgUrl] [nvarchar](512) NULL,15     [Title] [nvarchar](64) NULL,16     [Url] [nvarchar](256) NULL,17     [Remark] [nvarchar](max) NULL,18  CONSTRAINT [PK_dbo.Advertisement] PRIMARY KEY CLUSTERED 19 (20     [Id] ASC21 )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]22 ) ON [PRIMARY]23 24 GO
View Code

 

然后使用工具Scaffold-DbContext(数据库上下文脚手架)来生成model类文件和DbContext。

命令如下:

Scaffold-DbContext "server=.;database=XXX;uid=sa;pwd=密码;" Microsoft.EntityFrameworkCore.SqlServer -O Models -F  -Context BaseCoreContext 

在执行这个命令之前,需要将Model层设置为启动项目。否则会报错。

 

另外当你的项目Buid没有通过的话,会出现如下错误。

我一般的解决方案就是将其他项目全部先卸载,只留下一个Model,然后再执行以上语句。

这时,在你的Model项目下的Models文件夹下,就会出现如下文件:

打开BaseCoreContext.cs 文件,删除OnConfiguring 方法,至于为什么,我会在后面说明。

为了让数据库上下文也能用DI的方式进行使用,我新建了一个, IBaseContext接口,并且让BaseCoreContext 实现这个接口。

BaseCoreContext.cs

这个时候,仓储的基础父类应该是不会报错。但是我在BaseCoreContext里实现了一个分页操作,用到了一个PageModel 。需要添加到你的Model层里面

代码如下:

1 using System; 2 using System.Collections.Generic; 3 using System.Text; 4  5 namespace Sincere.Core.Model 6 { 7     ///  8     /// 通用分页信息类 9     /// 10     public class PageModel
11 {12 ///
13 /// 当前页标14 /// 15 public int page { get; set; } = 1;16 ///
17 /// 总页数18 /// 19 public int pageCount { get; set; } = 6;20 ///
21 /// 数据总数22 /// 23 public int dataCount { get; set; } = 0;24 ///
25 /// 每页大小26 /// 27 public int PageSize { set; get; }28 ///
29 /// 返回数据30 /// 31 public List
data { get; set; }32 33 }34 }
View Code

另外里面还有一些 转换函数,请参考源码:https://github.com/xzhencheng/Sincere.Core.git

至此,项目的仓储层的基础代码就构建完了,今天的作业就先写到这! 

 

转载于:https://www.cnblogs.com/xuzhencheng/p/11422025.html

你可能感兴趣的文章
对闭包的理解
查看>>
练习10-1 使用递归函数计算1到n之和(10 分
查看>>
Oracle MySQL yaSSL 不明细节缓冲区溢出漏洞2
查看>>
Code Snippet
查看>>
zoj 1232 Adventure of Super Mario
查看>>
组合数学 UVa 11538 Chess Queen
查看>>
oracle job
查看>>
Redis常用命令
查看>>
[转载]电脑小绝技
查看>>
windos系统定时执行批处理文件(bat文件)
查看>>
thinkphp如何实现伪静态
查看>>
BZOJ 2243: [SDOI2011]染色( 树链剖分 )
查看>>
BZOJ 1925: [Sdoi2010]地精部落( dp )
查看>>
c++中的string常用函数用法总结!
查看>>
[DLX精确覆盖+打表] hdu 2518 Dominoes
查看>>
SuperMap iServerJava 6R扩展领域开发及压力测试---判断点在那个面内(1)
查看>>
Week03-面向对象入门
查看>>
一个控制台程序,模拟机器人对话
查看>>
web.xml 中加载顺序
查看>>
pycharm激活地址
查看>>