最為一名越過菜鳥之後的開發,需要做介面開發。下面做一個純粹的介面程式設計的例項demo,僅僅是一個webapi介面的抽象。
下面是程式碼介面,AbsEFWork是webapi,BaseEntityFramework是一個介面庫。
先介紹一下webapi的實現,程式碼是從底層往上層寫的,閱讀程式碼的習慣應該是自上向下。
public class ProductController : CustomController<Product> { public ProductController(IEFCoreService<Product> efCoreService) : base(efCoreService) { } }
控制器程式碼很簡單的實現了CustomController,資料載體是Product。
using BaseEntityFramework.Implementations; using BaseEntityFramework.Implementations.Entitys; using BaseEntityFramework.IService; using Microsoft.EntityFrameworkCore; namespace BaseEntityFramework { public class Program { public static void Main(string[] args) { var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); builder.Services.AddDbContext<ProductDbContext>(options => options.UseInMemoryDatabase("memorydb")); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); builder.Services.AddScoped<IEFCoreService<Product>, EFCoreProductService>(); var app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); app.UseAuthorization(); app.MapControllers(); app.Run(); } } }
Program啟動程式需要實現IEFCoreService的注入,以及ProductDbContext 的記憶體實現。
這樣就可以啟動一個swagger
對於product資料儲存的具體實現,實體類product和dbcontext必須要自己去實現它。
public class Product:IEntity { [Key] public int Id { get; set; } public string Name { get; set; } public string Description { get; set; } [Column(TypeName = "decimal(28,16)")] public decimal Price { get; set; } }
using BaseEntityFramework.Implementations.Entitys; using Microsoft.EntityFrameworkCore; namespace BaseEntityFramework.Implementations { public class ProductDbContext:DbContext { public ProductDbContext(DbContextOptions<ProductDbContext> dbContextOptions):base(dbContextOptions) { } public DbSet<Product> Products { get; set; } } }
檢視上面的控制器程式碼,有注入IEFCoreService<Product>的業務程式碼,對於介面肯定是需要一個實現,這裡可以再次封裝一個抽象的基類來(溫馨提示:重複的程式碼,必須最佳化),我這裡暫時沒做處理。
using BaseEntityFramework.Implementations.Entitys; using BaseEntityFramework.IService; using BaseEntityFramework.Models; using Microsoft.EntityFrameworkCore; using System.Linq.Expressions; namespace BaseEntityFramework.Implementations { public class EFCoreProductService : IEFCoreService<Product> { private readonly ProductDbContext _dbContext; public EFCoreProductService(ProductDbContext productDbContext) { _dbContext = productDbContext; } public async Task<bool> Add(Product entity) { _dbContext.Products.Add(entity); var result = await _dbContext.SaveChangesAsync(); return result != 0; } public Task<bool> Delete(Product entity) { throw new NotImplementedException(); } public async Task<IEnumerable<Product>> GetAll() { var result =await _dbContext.Products.ToListAsync(); return result; } public Task<Product> GetEntity(Expression<Func<Product, bool>> expression) { throw new NotImplementedException(); } public async Task<IReadOnlyCollection<Product>> GetList(Expression<Func<Product, bool>> expression) { var result = await _dbContext.Products.Where(expression).ToListAsync(); return result.AsReadOnly(); } public Task<PageResult<Product>> GetPageResult<Req>(PageInput<Req> pagInput) where Req : new() { throw new NotImplementedException(); } public Task<bool> Update(Product entity) { throw new NotImplementedException(); } } }
上面的程式碼很簡單易懂,最大的好處就是可以複用。實體類和 dbcontext越多這個簡簡單單的結構就越是有用。
BaseEntityFramework的核心邏輯就是把業務程式碼做了抽象,做了一個統一的模板,不管 是從那方便說都只有好處。而且作為開發只關心自己的業務程式碼這一塊。
public interface IEFCoreService<T> where T:IEntity { Task<bool> Add(T entity) ; Task<bool> Delete(T entity); Task<bool> Update(T entity); Task<IReadOnlyCollection<T>> GetList(Expression<Func<T,bool>> expression) ; Task<PageResult<T>> GetPageResult<Req>(PageInput<Req> pagInput) where Req:new(); Task<T> GetEntity(Expression<Func<T, bool>> expression); Task<IEnumerable<T>> GetAll(); }
以上的例項只是一個簡單的demo,專案中需要做框架的話這或許是一個開始,需要做的遠遠不止這些。
原始碼:
liuzhixin405/AbsEFWork (github.com)