搭建WebAPI项目,EF Core访问数据库
1. 新建项目,搭建架构,Api 采用 .NET Core 5.0 ,类库采用 .NET 5.0

项目引用顺序:表现层引用业务层,业务层引用数据访问层、公共类,公共类引用扩展类
2. 采用数据库先行模式,实现模型层
Nuget(注意版本兼容):
Pomelo.EntityFrameworkCore.MySql(根据数据库不同而不同,这里采用的是MYSQL)
Microsoft.EntityFrameworkCore.Design
Microsoft.EntityFrameworkCore.Tools
设置数据访问层为启动项目,打开程序包管理器控制台,执行上下文脚手架命令:
Scaffold-DbContext "Server=localhost;User Id=root;Password=密码;Database=数据库名称;TreatTinyAsBoolean=true;" "Pomelo.EntityFrameworkCore.MySql" -OutputDir Models -force -UseDatabaseNames
生成效果:

另外添加 AppDbContext.cs ,代替******Context.cs

3. 添加 IHospitalServices类,实现接口层(仅医院表,下同)
public interface IHospitalServices { /// <summary> /// 获取数据集合 /// </summary> /// <returns></returns> Task<IEnumerable<hospital>> GetListAsync(); /// <summary> /// 通过主键ID获取数据 /// </summary> Task<hospital> GetInfoAsync(string id); /// <summary> /// 添加数据 /// </summary> Task<int> AddAsync(hospital entity); /// <summary> /// 添加数据集合 /// </summary> Task<int> AddListAsync(List<hospital> list); /// <summary> /// 更新一条数据 /// </summary> Task<int> UpdateAsync(hospital entity); /// <summary> /// 修改集合,修改指定的列 /// </summary> /// <param name="list">集合</param> /// <param name="column">指定的列,参考 id,name。要修改的列名传入数组</param> /// <returns></returns> Task<int> UpdateListAsync(List<hospital> list, string[] column); /// <summary> /// 删除数据 /// </summary> Task<int> DeleteAsync(string id); /// <summary> /// 删除集合 /// </summary> Task<int> DeleteListAsync(List<hospital> list); /// <summary> /// 条件查询 /// </summary> /// <param name="where">过滤条件</param> Task<IEnumerable<hospital>> GetAnyAsync(Expression<Func<hospital, bool>> where); /// <summary> /// 分页查询 /// </summary> /// <param name="where">过滤条件</param> /// <param name="courrentPage">当前页</param> /// <param name="pageSize">页大小</param> /// <returns></returns> Task<page_data<hospital>> GetAnyAsync<TOrder>(Expression<Func<hospital, bool>> where, Expression<Func<hospital, TOrder>> order, int pageIndex = 1, int pageSize = 15, bool isDesc = false); }
需要扩展模型类,用于接收 Api 的请求参数和分页返回数据
/// <summary> /// 分页查询接收 /// </summary> public class page_info<T> where T : class { /// <summary> /// 第几页 /// </summary> public int page_index { get; set; } /// <summary> /// 单页数 /// </summary> public int page_size { get; set; } /// <summary> /// 数据 /// </summary> public T data { get; set; } } /// <summary> /// 分页查询返回 /// </summary> public class page_data<T> where T : class { /// <summary> /// 总页数 /// </summary> public int total_page { get; set; } /// <summary> /// 总数 /// </summary> public int total_count { get; set; } /// <summary> /// 数据 /// </summary> public IEnumerable<T> data { get; set; } } /// <summary> /// 修改/删除方法的接收 /// </summary> public class receive_data { /// <summary> /// 值,以逗号分割 /// </summary> public string ids { get; set; } /// <summary> /// 修改状态 -1删除 0禁用 1启用 /// </summary> public int? status { get; set; } }
4. 添加 HospitalServices类,实现业务逻辑层
public class HospitalServices : IHospitalServices { private readonly AppDbContext context; public HospitalServices(AppDbContext context) { this.context = context; } public async Task<IEnumerable<hospital>> GetListAsync() { return await context.hospital.ToListAsync(); } public async Task<hospital> GetInfoAsync(string id) { return await context.hospital.FindAsync(new Guid(id)); } public async Task<int> AddAsync(hospital entity) { await context.hospital.AddAsync(entity); return await context.SaveChangesAsync(); } public async Task<int> AddListAsync(List<hospital> list) { await context.hospital.AddRangeAsync(list); return await context.SaveChangesAsync(); } public async Task<int> UpdateAsync(hospital entity) { var entry = this.context.hospital.Update(entity); return await context.SaveChangesAsync(); } public async Task<int> UpdateListAsync(List<hospital> list, string[] column) { foreach (var entity in list) { var entry = context.Entry(entity); entry.State = EntityState.Modified; foreach (var item in column) { entry.Property(item).IsModified = true; } var listP = entry.Properties.ToList(); listP.RemoveAll(w => w.Metadata.IsPrimaryKey()); foreach (var item in listP) { if (column.Contains(item.Metadata.Name))//字段名称 continue; item.IsModified = false; } } return await context.SaveChangesAsync(); } public async Task<int> DeleteAsync(string id) { var entity = await context.hospital.FindAsync(new Guid(id)); if (entity != null) { //先删除关联表数据 //…… context.hospital.Remove(entity); return await context.SaveChangesAsync(); } return 0; } public async Task<int> DeleteListAsync(List<hospital> list) { //先删除关联表数据 //…… context.hospital.RemoveRange(list); return await context.SaveChangesAsync(); } public async Task<IEnumerable<hospital>> GetAnyAsync(Expression<Func<hospital, bool>> where) { return await context.hospital.AsNoTracking().Where(where).ToArrayAsync(); } public async Task<page_data<hospital>> GetAnyAsync<TOrder>(Expression<Func<hospital, bool>> where, Expression<Func<hospital, TOrder>> order, int pageIndex = 1, int pageSize = 15, bool isDesc = false) { page_data<hospital> data = new page_data<hospital>(); int totalCount = await context.hospital.AsNoTracking().Where(where).CountAsync(); if (isDesc) data.data = await context.hospital.AsNoTracking().Where(where).OrderByDescending(order).Skip(pageSize * (pageIndex - 1)).Take(pageSize).ToArrayAsync(); else data.data = await context.hospital.AsNoTracking().Where(where).OrderBy(order).Skip(pageSize * (pageIndex - 1)).Take(pageSize).ToArrayAsync(); data.total_page = (totalCount + pageSize - 1) / pageSize; data.total_count = totalCount; return data; } }
5. 添加 HospitalController控制器,实现表现层
/// <summary> /// 医院管理 /// </summary> [Route("api/[controller]")] [ApiController] public class HospitalController : ControllerBase { private readonly IHospitalServices idal; Result result = new Result(); public HospitalController(IHospitalServices idal) { this.idal = idal; } /// <summary> /// 获取医院详细信息 /// </summary> /// <param name="id">医院ID</param> /// <returns></returns> [HttpGet] [Route("getInfo")] public async Task<Result> Get(string id) { try { result.Data = await idal.GetInfoAsync(id); return result; } catch (Exception ex) { result.Code = -99; result.Message = ex.Message; return result; } } /// <summary> /// 添加医院信息 /// </summary> /// <param name="json">{"name":"第一测试医院", "hospital_code":"00280099", "areacode":"778899"}</param> /// <returns></returns> [HttpPost] [Route("addInfo")] public async Task<Result> AddInfo(object json) { try { var model = json.ToString().ToObject<hospital>(); model.id = Guid.NewGuid(); model.acronym = MsPinYinHelper.FirstPinYin(model.name); model.create_time = DateTime.Now; model.status = 1; int count = await idal.AddAsync(model); if (count > 0) { result.Message = "添加成功!"; result.Data = count; } else { result.Code = -1; result.Message = "添加失败!"; } return result; } catch (Exception ex) { result.Code = -99; result.Message = ex.Message; return result; } } /// <summary> /// -1删除/0禁用/1启用 /// </summary> /// <param name="json">{"ids":"1d235515-b464-4de4-8777-ebcd6053e1cf,cd402518-1338-4f18-84d3-9423e06f6637","status":1}</param> /// <returns></returns> [HttpPost] [Route("updateStatus")] public async Task<Result> UpdateStatus(object json) { try { receive_data model = json.ToString().ToObject<receive_data>(); string message = ""; List<hospital> list = new List<hospital>(); foreach (var id in model.ids.Split(",")) { var entity = await idal.GetInfoAsync(id); if (entity != null) { switch (model.status) { case -1: message = "删除"; entity.status = -1; break; case 1: message = "启用"; entity.status = 1; break; default: message = "禁用"; entity.status = 0; break; } list.Add(entity); } } int count = await idal.UpdateListAsync(list, new string[] { "status" }); if (count > 0) { result.Message = message + "成功!"; result.Data = count; } else { result.Code = -1; result.Message = message + "失败!"; } return result; } catch (Exception ex) { result.Code = -99; result.Message = ex.Message; return result; } } /// <summary> /// 修改医院信息 /// </summary> /// <param name="json">{"id":"cd402518-1338-4f18-84d3-9423e06f6637","hospital_id":"00280099","name":"第二测试医院","acronym":"decsyy","create_time": "2021-05-31T15:52:08","status": 1}</param> /// <returns></returns> [HttpPost] [Route("updateInfo")] public async Task<Result> UpdateInfo(object json) { try { var entity = json.ToString().ToObject<hospital>(); Expression<Func<hospital, bool>> filter = u => u.id == entity.id; var model = idal.GetAnyAsync(filter).Result.FirstOrDefault(); if (model != null) { PropertyTrade.Voluation(model, entity); int count = await idal.UpdateAsync(model); if (count > 0) { result.Message = "修改成功!"; result.Data = count; } else { result.Code = -1; result.Message = "修改失败!"; } } else { result.Code = -1; result.Message = "找不到该数据!"; } return result; } catch (Exception ex) { result.Code = -99; result.Message = ex.Message; return result; } } /// <summary> /// 分页查询医院列表信息 /// </summary> /// <param name="json">{"page_index":1,"page_size":10,"data":{"name":"医院","status":1}}</param> /// <returns></returns> [HttpPost] [Route("getAny")] public async Task<Result> GetAny(object json) { try { page_info<hospitalDro> data = json.ToString().ToObject<page_info<hospitalDro>>(); Expression<Func<hospital, bool>> filter = u => u.status != -1; if (data.data != null) { if (!string.IsNullOrEmpty(data.data.name)) filter = filter.And(c => c.name.Contains(data.data.name)); if (data.data.status != null) filter = filter.And(c => c.status == data.data.status); } Expression<Func<hospital, DateTime>> order = u => u.create_time; result.Data = await idal.GetAnyAsync(filter, order, data.page_index, data.page_size, true); return result; } catch (Exception ex) { result.Code = -99; result.Message = ex.Message; return result; } } public partial class hospitalDro { public string name { get; set; } public sbyte? status { get; set; } } }
需要扩展模型类,用于 Api 返回数据
public class Result { /// <summary> /// 返回状态 0正常 -1失败 -99程序异常 /// </summary> public int Code { get; set; } /// <summary> /// 提示信息,失败提示失败,成功提示成功(除查询),异常提醒异常信息 /// </summary> public string Message { get; set; } /// <summary> /// 返回数据,正常时返回 /// </summary> public object Data { get; set; } }
还需添加 ExpressionExtensions类 和 PropertyTrade类,
详见 https://www.cnblogs.com/Allofus/p/14771510.html,https://www.cnblogs.com/Allofus/p/14848681.html
6. 在 appsettings.json 中配置数据库连接字符串
"AllowedHosts": "*", "ConnectionStrings": { "DBConnection": "server=localhost;user=root;pwd=123456;database=数据库名" }
7. 在 Startup类 ConfigureServices方法 中进行依赖注入
//EF Core DbContext类 var connectionString = Configuration.GetConnectionString("DBConnection"); ServerVersion serverVersion = ServerVersion.AutoDetect(connectionString); services.AddDbContextPool<AppDbContext>( options => options.UseMySql(connectionString, serverVersion) ); services.AddScoped<IHospitalServices, HospitalServices>();
完成,这样就可以操作数据表里面的数据了:(下述用的是其他图片,所以不是Hospital而是User)

8. 没有注释不友好?设置项目属性--生成,勾选XML文档文件,如下图:

再在ConfigureServices方法中进行配置:
services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "API", Version = "v1" }); // 为 Swagger 设置xml文档注释路径 var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); // 添加控制器层注释,true表示显示控制器注释 c.IncludeXmlComments(xmlPath, true); });
最后在控制器上添加注释:
/// <summary> /// 获取用户列表 /// </summary> [HttpGet] [Route("getUserList")] public IEnumerable<User> Get() { return _user.GetAllUsers(); }
效果如下图:
![]()
参考上传文件 WebApi_阶段一.zip
弊端:修改时,int字段会为0

浙公网安备 33010602011771号