使用EfCore.GenericServices加速你的CRUD操作
EfCore.GenericServices 是一个强大的库,专为使用 Entity Framework Core 的 Web、移动和桌面应用提供快速创建、读取、更新和删除(CRUD)功能。它以适配器和命令模式工作,简化了数据库与前端系统之间的交互。
这个库在NuGet上可用,遵循MIT许可证,详细变更记录可参考ReleaseNotes。
支持的.NET框架版本
- 版本 6.?.?: 支持.NET 6, 7 和 8
- 版本 5.2.?: 支持.NET 5, 6 和 7
对于低于.NET 5的版本, EfCore.GenericServices 不再支持。
文档与文章资源
在GitHub Wiki中可以找到详细的文档。以下是一些深入解释库功能的文章:
- GenericServices:一个从EF Core数据库提供CRUD前端服务的库
- 提升EfCore.GenericServices的领域驱动设计更新性能 - 适用于版本 3.1.0 及以上
- GenericServices设计哲学以及技巧和技巧
库的功能
该库利用了一个事实:虽然四种CRUD数据库访问方式有各自不同的行为,但它们都有共同的数据部分——要访问的类或表以及其属性。通过定义DTO(数据传输对象,也称为ViewModel)以及特殊接口,你可以确定类或表以及要访问的属性。这使得库能为每种CRUD操作实现通用解决方案,而唯一变化的是使用的DTO名称。
典型的Web应用程序可能有数百个CRUD页面,如显示这个,编辑那个,删除另一个。每个CRUD访问都需要将数据库中的数据适应给用户展示,并处理用户的更改。使用 EfCore.GenericServices ,只需为特定应用创建一套更新代码,然后将其复制/粘贴并修改一行(DTO名称)即可应用于所有其他版本。
我个人主要使用ASP.NET Core,所以示例都基于ASP.NET Core,但 EfCore.GenericServices 可用于任何NET Core类型的应用程序(我知道有人将其用于WPF)。
EF Core 5及更高版本的限制
ILinkToEntity<TEntity>
接口无法处理映射到多个表的实体类。
使用 EfCore.GenericServices 的代码示例
在ASP.NET Core MVC控制器中,可以这样使用:
public class BookController
private ICrudServices _service;
public BookController(ICrudServices service)
{
_service = service;
}
public ActionResult Index()
{
var dataToDisplay = _service.ReadManyNoTracked<BookListDto>().ToList()
return View(dataToDisplay);
}
//... 其他方法...
对于ASP.NET Core Razor Pages,这是添加书评的完整代码,来源于示例Razor Page应用程序:
public class AddReviewModel : PageModel
{
private readonly ICrudServices _service;
public AddReviewModel(ICrudServices service)
{
_service = service;
}
[BindProperty]
public AddReviewDto Data { get; set; }
public void OnGet(int id)
{
Data = _service.ReadSingle<AddReviewDto>(id);
if (!_service.IsValid)
{
_service.CopyErrorsToModelState(ModelState, Data, nameof(Data));
}
}
public IActionResult OnPost()
{
if (!ModelState.IsValid)
{
return Page();
}
_service.UpdateAndSave(Data);
if (_service.IsValid)
return RedirectToPage("BookUpdated", new { message = _service.Message });
//错误状态
_service.CopyErrorsToModelState(ModelState, Data, nameof(Data));
return Page();
}
}
在ASP.NET Core Web API中,EfCore.GenericServices.AspNetCore
提供了帮助返回正确数据格式的扩展方法以及其他允许使用 EfCore.GenericServices 进行Web API动作单元测试的方法。以下是来自 TodoController
示例的一部分:
public class ToDoController : ControllerBase
{
[HttpGet]
public async Task<ActionResult<WebApiMessageAndResult<List<TodoItem>>>> GetManyAsync([FromServices]ICrudServices service)
{
return service.Response(await service.ReadManyNoTracked<TodoItem>().ToListAsync());
}
[Route("name")]
[HttpPatch()]
public ActionResult<WebApiMessageOnly> Name(ChangeNameDto dto, [FromServices]ICrudServices service)
{
service.UpdateAndSave(dto);
return service.Response();
//... 其他行动方法...
}
技术特性
EfCore.GenericServices(NuGet链接),是一个开放源代码(MIT许可)的netcoreapp2.0库,假设您使用EF Core进行数据库访问。它与依赖注入(如ASP.NET Core的DI服务)很好地配合工作,同时也包含了非DI基础的简单配置系统,适合单元测试和/或无服务器应用。
该库旨在兼容标准样式(例如,公开属性设置器和公共无参构造函数)的实体类和领域驱动设计(DDD)样式的实体类(其中所有的更新都是通过实体类中命名的方法完成)。它还与DTO一起工作,提供了安全的只读属性标记,确保这些属性不会被用于数据库更新。
从我在2014年创建的类似GenericServices库中学到的经验,结合EF Core的新特性和DDD能力,我们重新构想了这个库,使其更加简单易用。在单个项目中,我估计它节省了我大约两个月的时间,让我的开发变得高效且有趣。