如何在 ASP.NET 核心 Web API 中管理 EFCore DbContext 生命周期?



我正在实现 3 层架构,我的问题是:我应该在哪里调用SaveChanges();(如果适用(?我应该在哪里创建和提交事务?请阅读整个问题。

在下面的代码中,我只有"读取"操作,但你会得到架构的概念。我正在为这个决定而苦苦挣扎,但我提出了两个选择:

  1. Core项目中引用 EFCore。将 DbContext 注入到类Service并通过方法将其注入数据层。喜欢这个:

    public class ItemService
    {
    private MyContext _ctx;
    private readonly IItemData _itemData;   
    public ItemService(IItemData itemData)
    {
    _itemData = itemData;
    }   
    public void InjectCtx(MyContext ctx)
    {
    _ctx = ctx;
    _itemData.InjectCtx(_ctx);
    }   
    public void Operation(int itemId)
    {
    using (var transaction = _ctx.Database.BeginTransaction())
    {
    //Do something  
    _ctx.SaveChanges();
    transaction.Commit();
    }
    }
    }
    
  2. 在工作单元对象的Core中创建一个接口。其中将具有保存更改和事务,提交方法。然后在数据层中实现它们,并在Service类中进行相应的调用。

这是代码。我有 3 个项目:

  • Infrstructure(数据( -参考核心和EFCore
  • 核心(业务逻辑( -无依赖关系
  • Web API(MVC 项目( -参考 Core、Data 和 EFCore

- 核心(没有依赖项,甚至没有对 EFCore 的引用(:

public class ItemDto
{
public int ItemId { get; set; }
public string Name { get; set; }
}
public interface IItemData
{
Task<ItemDto> GetItem(int itemId);
}
public class ItemService
{
private readonly IItemData _itemData;
public ItemService(IItemData itemData)
{
_itemData = itemData;
}
public async Task<ItemDto> GetItem(int itemId)
{
return await _itemData.GetItem(itemId);
}
}

- 数据(参考核心项目和EFCore(

public class ItemData : IItemData
{
private readonly MyContext _ctx;
public ItemData(MyContext ctx)
{
_ctx = ctx;
}
public async Task<ItemDto> GetItem(int itemId)
{
var item = await _ctx.Items
.Where(i => i.ItemId == itemId)
.Select(row => new ItemDto()
{
ItemId = row.ItemId,
Name = row.ItemName
})
.FirstOrDefaultAsync();
return item;
}
}

- 网页接口:

[Route("api/[controller]")]
[ApiController]
public class ItemsController : ControllerBase
{
private readonly ItemService _itemService;
public ItemsController(ItemService itemService)
{
_itemService = itemService;
}
[HttpGet("{itemId}")]
public async Task<ItemDto> Get(int itemId)
{
return await _itemService.GetItem(itemId);
}
}

如果你真的觉得你需要交易,我会尝试在你的服务之上处理它们,这样那些人就不负责处理它们。

执行此操作的一种方法可以是:

  • 使用作用域内的DbContext

  • 当请求启动或调用服务方法时,使用Database.BeginTransaction()创建事务。

  • 服务层调用数据层并处理业务逻辑。

  • 您的数据层.SaveChanges()应用到任何需要的地方。

  • 当请求结束或服务方法调用结束时,运行transaction.Commit()transaction.Rollback()

在不让您的服务负责的情况下实现这些事务创建/提交/回滚的一种方法是使用过滤器、中间件或拦截器。

最新更新