1.配景
工作以后,大部门时间都是在做基于业务的CRUD工作,软件产物或者项目的框架基本都早就搭建好了,步伐员只需要在框架内去填格子打代码就行了。于是,我抽了时间来搭建个简单的三层架构模式的web api项目,技能点大概如下:三层架构+EFCore+.Net 8.0 Web Api+AutoMap+IOC容器。本文是我搭建项目的一个过程,比较简单和粗糙,但是完备,得当学习和练手。
2.操作
2.1 项目的架构图
其实图1是我最开始的设计布局,但是设计风格有提到:模块间应该依赖抽象,而不是详细的实现。所以我将布局改造为了图2,针对业务逻辑层和数据访问层开了一个抽象接口层。
2.2 新增项目
按照如下操作,创建项目:SimpleWebApi
2.3 新增类库
按照下图新增类库:SimpleWebApi.Migration、SimpleWebApi.Business.Service、SimpleWebApi.Business.Service.Interface
注意:SimpleWebApi.Migration是数据库访问
SimpleWebApi.Business.Service、SimpleWebApi.Business.Service.Interface是做业务逻辑
2.4 支持EFCore
找到类库:SimpleWebApi.Migration,并给这个项目,添加如下nuget包:Microsoft.EntityFrameworkCore、Microsoft.EntityFrameworkCore.SqlServer、Microsoft.EntityFrameworkCore.Tools、Microsoft.EntityFrameworkCore.Design
按照如下所示:添加Model和DBContext
Commodity的代码如下:
- using System;
- using System.Collections.Generic;
- namespace SimpleWebApi.Migration.Models;
- public partial class Commodity
- {
- public int Id { get; set; }
- public long? ProductId { get; set; }
- public int? CategoryId { get; set; }
- public string? Title { get; set; }
- public decimal? Price { get; set; }
- public string? Url { get; set; }
- public string? ImageUrl { get; set; }
- }
复制代码 CompanyInfo的代码如下:
- using System;
- using System.Collections.Generic;
- namespace SimpleWebApi.Migration.Models;
- public partial class CompanyInfo
- {
- public int CompanyId { get; set; }
- public string? Name { get; set; }
- public DateTime? CreateTime { get; set; }
- public int CreatorId { get; set; }
- public int? LastModifierId { get; set; }
- public DateTime? LastModifyTime { get; set; }
- public virtual ICollection<SysUser> SysUsers { get; set; } = new List<SysUser>();
- }
复制代码 SysUser的代码如下:
- using System;
- using System.Collections.Generic;
- namespace SimpleWebApi.Migration.Models;
- public partial class SysUser
- {
- public int Id { get; set; }
- public string? Name { get; set; }
- public string? Password { get; set; }
- public int Status { get; set; }
- public string? Phone { get; set; }
- public string? Mobile { get; set; }
- public string? Address { get; set; }
- public string? Email { get; set; }
- public long? Qq { get; set; }
- public string? WeChat { get; set; }
- public int? Sex { get; set; }
- public DateTime? LastLoginTime { get; set; }
- public DateTime? CreateTime { get; set; }
- public int? CreateId { get; set; }
- public DateTime? LastModifyTime { get; set; }
- public int? LastModifyId { get; set; }
- public int? CompanyId { get; set; }
- public virtual CompanyInfo? Company { get; set; }
- }
复制代码 AdvancedCustomerDbContext的代码如下:
2.5 业务逻辑抽象层
找到项目“SimpleWebApi.Business.Service.Interface”,新增项目引用-SimpleWebApi.Migration,如下图:
按照下图添加以下接口:
IBaseService的代码如下:
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Linq.Expressions;
- using System.Text;
- using System.Threading.Tasks;
- namespace SimpleWebApi.Business.Service.Interface
- {
- public interface IBaseService
- {
- public IQueryable<T> Query<T>(Expression<Func<T,bool>> funcWhere) where T : class;
- }
- }
复制代码 ICommodityService的代码如下:
- using SimpleWebApi.Migration.Models;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- namespace SimpleWebApi.Business.Service.Interface
- {
- public interface ICommodityService:IBaseService
- {
- public bool AddCommodity(Commodity commodity);
- public IQueryable<Commodity> GetCommodity(int Id);
-
- }
- }
复制代码 ICompanyInfoService的代码如下:
- using SimpleWebApi.Migration.Models;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- namespace SimpleWebApi.Business.Service.Interface
- {
- public interface ICompanyInfoService:IBaseService
- {
- CompanyInfo GetCompany(int companyID);
- }
- }
复制代码 ISysUserService的代码如下:
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- namespace SimpleWebApi.Business.Service.Interface
- {
- public interface ISysUserService:IBaseService
- {
- }
- }
复制代码 2.6 业务逻辑层
找到项目“SimpleWebApi.Business.Service”,新增项目引用如下:SimpleWebApi.Business.Service.Interface和 SimpleWebApi.Migration
按照下图添加以下类:
BaseService的代码如下:
- using Microsoft.EntityFrameworkCore;
- using SimpleWebApi.Business.Service.Interface;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Linq.Expressions;
- using System.Text;
- using System.Threading.Tasks;
- namespace SimpleWebApi.Business.Service
- {
- public class BaseService:IBaseService
- {
- protected DbContext Context;
- public BaseService(DbContext context)
- {
- Console.WriteLine($"{this.GetType().Name}被构造了......");
- this.Context= context;
- }
- public IQueryable<T> Query<T>(Expression<Func<T, bool>> funcWhere) where T : class
- {
- return this.Context.Set<T>().Where<T>(funcWhere);
- }
-
- }
- }
复制代码
CommodityService的代码如下:
- using Microsoft.EntityFrameworkCore;
- using SimpleWebApi.Business.Service.Interface;
- using SimpleWebApi.Migration.Models;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- namespace SimpleWebApi.Business.Service
- {
- public class CommodityService : BaseService, ICommodityService
- {
- public CommodityService(DbContext context):base(context)
- {
-
- }
- public bool AddCommodity(Commodity commodity)
- {
- this.Context.Set<Commodity>().Add(commodity);
- int num= this.Context.SaveChanges();
- return num > 0;
- }
- public IQueryable<Commodity> GetCommodity(int Id)
- {
- var list= this.Context.Set<Commodity>().Where(a => a.Id == Id);
- return list;
- }
- }
- }
复制代码
CompanyInfoService的代码如下:
- using Microsoft.EntityFrameworkCore;
- using SimpleWebApi.Business.Service.Interface;
- using SimpleWebApi.Migration.Models;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- namespace SimpleWebApi.Business.Service
- {
- public class CompanyInfoService:BaseService, ICompanyInfoService
- {
- public CompanyInfoService(DbContext context):base(context)
- {
-
- }
- public CompanyInfo GetCompany(int companyID)
- {
- var company = this.Context.Set<CompanyInfo>().Where(a=>a.CompanyId==companyID).FirstOrDefault();
- return company;
- }
- }
- }
复制代码
SysUserService的代码如下:
- using Microsoft.EntityFrameworkCore;
- using SimpleWebApi.Business.Service.Interface;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- namespace SimpleWebApi.Business.Service
- {
- public class SysUserService:BaseService, ISysUserService
- {
- public SysUserService(DbContext context) : base(context)
- {
-
- }
- }
- }
复制代码 2.6 UI
找到项目“SimpleWebApi”,并新增项目引用:
SimpleWebApi.Business.Service、SimpleWebApi.Business.Service.Interface、SimpleWebApi.Migration
按照如下,新增nuget包引用:AutoMapper、AutoMapper.Extensions.Microsoft.DependencyInjection
新增文件夹DTO和Map,并新增类文件和AutoMapper的规则文件
CommodityDTO的代码如下:
- using System;
- using System.Collections.Generic;
- namespace SimpleWebApi;
- public class CommodityDTO
- {
- public int CommodityId { get; set; }
- public long? ProductId { get; set; }
- public int? CategoryId { get; set; }
- public string? Title { get; set; }
- public decimal? Price { get; set; }
- public string? Url { get; set; }
- public string? ImageUrl { get; set; }
- }
复制代码 CompanyInfoDTO的代码如下:
- using SimpleWebApi.Migration.Models;
- using System;
- using System.Collections.Generic;
- namespace SimpleWebApi;
- public class CompanyInfoDTO
- {
- public int CompanyId { get; set; }
- public string? Name { get; set; }
- public DateTime? CreateTime { get; set; }
- public int CreatorId { get; set; }
- public int? LastModifierId { get; set; }
- public DateTime? LastModifyTime { get; set; }
- public virtual ICollection<SysUser> SysUsers { get; set; } = new List<SysUser>();
- }
复制代码 AuotoMapConfig的代码如下:
- using AutoMapper;
- using SimpleWebApi.Migration.Models;
- namespace SimpleWebApi
- {
- public class AuotoMapConfig:Profile
- {
- public AuotoMapConfig()
- {
- CreateMap<Commodity, CommodityDTO>().ForMember(c=>c.CommodityId, s=>s.MapFrom(c=>c.Id))
- .ForMember(c=>c.ProductId,s=>s.MapFrom(c=>c.ProductId))
- .ForMember(c=>c.CategoryId,s=>s.MapFrom(c=>c.CategoryId))
- .ForMember(c=>c.Title,s=>s.MapFrom(c=>c.Title))
- .ForMember(c=>c.Price,s=>s.MapFrom(c=>c.Price))
- .ForMember(c=>c.Url,s=>s.MapFrom(c=>c.Url))
- .ForMember(c=>c.ImageUrl,s=>s.MapFrom(c=>c.ImageUrl));
- CreateMap<CompanyInfo, CompanyInfoDTO>();
- }
- }
- }
复制代码 为了添加对象映射,DBContext,对象注入等,打开Program文件,按照如下添加


上图的红色代码如下:
- //查询数据库真实数据的业务逻辑层服务注册
- builder.Services.AddTransient<ICommodityService, CommodityService>();
- builder.Services.AddTransient<ICompanyInfoService, CompanyInfoService>();
- //添加DbContext
- //builder.Services.AddDbContext<AdvancedCustomerDbContext>();
- builder.Services.AddTransient<DbContext, AdvancedCustomerDbContext>();
- //支持AutoMapper
- builder.Services.AddAutoMapper(options =>
- {
- options.AddProfile<AuotoMapConfig>();
- });
复制代码 选中“Controllers”文件夹新增控制器 ApiController

ApiController代码如下:
- using AutoMapper;
- using Microsoft.AspNetCore.Mvc;
- using SimpleWebApi.Business.Service.Interface;
- using SimpleWebApi.Migration.Models;
- using System.Linq.Expressions;
- namespace SimpleWebApi.Controllers
- {
- [ApiController]
- [Route("api/[controller]/[action]")]
- public class ApiController : ControllerBase
- {
- private readonly ILogger<ApiController> _logger;
- private ICommodityService _comService;
- private ICompanyInfoService _companyService;
- private IMapper _mapper;
- public ApiController(ILogger<ApiController> logger, ICommodityService comService, ICompanyInfoService companyService, IMapper mapper)
- {
- _logger = logger;
- _comService = comService;
- _companyService = companyService;
- _mapper = mapper;
- }
- [HttpGet]
- public IEnumerable<CommodityDTO> GetCommodity(int Id)
- {
- Expression<Func<Commodity, bool>> funcWhere = null;
- funcWhere = a => a.Id == Id;
- var commodityList = _comService.Query(funcWhere);
- List<CommodityDTO> list = new List<CommodityDTO>();
- _mapper.Map<IQueryable<Commodity>, List<CommodityDTO>>(commodityList, list);
- return list;
- }
- [HttpGet]
- public CompanyInfoDTO GetCompanyInfo(int companyId)
- {
- var company = _companyService.GetCompany(companyId);
- CompanyInfoDTO dto = new CompanyInfoDTO();
- _mapper.Map<CompanyInfo, CompanyInfoDTO>(company, dto);
- return dto;
- }
- }
- }
复制代码 这里有个小坑,打开SimpleWebApi.csproj,按照下图设置,可以办理题目
- <InvariantGlobalization>false</InvariantGlobalization>
复制代码
ps:默认该数据值是true,运行步伐后会非常,非常提示如下:
- System.Globalization.CultureNotFoundException
- HResult=0x80070057
- Message=Only the invariant culture is supported in globalization-invariant mode. See https://aka.ms/GlobalizationInvariantMode for more information. (Parameter 'name')
- en-us is an invalid culture identifier.
- Source=System.Private.CoreLib
- StackTrace:
- 在 System.Globalization.CultureInfo.GetCultureInfo(String name)
- 在 Microsoft.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry, SqlConnectionOverrides overrides)
- 在 Microsoft.Data.SqlClient.SqlConnection.Open(SqlConnectionOverrides overrides)
- 在 Microsoft.Data.SqlClient.SqlConnection.Open()
- 在 Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerConnection.OpenDbConnection(Boolean errorsExpected)
- 在 Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenInternal(Boolean errorsExpected)
- 在 Microsoft.EntityFrameworkCore.Storage.RelationalConnection.Open(Boolean errorsExpected)
- 在 Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReader(RelationalCommandParameterObject parameterObject)
- 在 Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.InitializeReader(Enumerator enumerator)
- 在 Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.<>c.<MoveNext>b__21_0(DbContext _, Enumerator enumerator)
- 在 Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
- 在 Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.MoveNext()
- 在 System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
- 在 System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
- 在 SimpleProjectDemo.Controllers.WeatherForecastController.Get2() 在 E:\Vs_Project\SimpleProjectDemo\SimpleProjectDemo\Controllers\WeatherForecastController.cs 中: 第 50 行
- 在 Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncObjectResultExecutor.Execute(ActionContext actionContext, IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
- 在 Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<<InvokeActionMethodAsync>g__Logged|12_1>d.MoveNext()
复制代码 2.7 运行项目
运行项目,如下图所示显示Swagger页面:
用接口api/Api/GetCommodity 来测试下
3.结论
至此,操作完成。成功的搭建了一个简单的.net 8.0的web api项目。
ps:本项目的代码都很简单,朴拙建议跟着指引来敲代码梳理思路,不过思量极端情况,我还是打包代码上传到了csdn。有需要的童鞋可以按需下载。谢谢。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |