Я реализую 3-уровневую архитектуру, и мой вопрос: Куда мне звонить SaveChanges();
(если применимо)? Где я должен создать и совершить транзакцию? Пожалуйста, прочитайте весь вопрос.
В приведенном ниже коде у меня есть только операция чтения, но вы получите представление об архитектуре. Я борюсь с решением, но у меня есть два варианта:
Ссылка EFCore в проекте Core
. Вставьте 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();
}
}
}
Создайте интерфейс в Core
для объекта Единица работы. Которые будут иметь методы SaveChanges и Transaction, Commit. Затем реализуйте их на уровне данных и, соответственно, вызовите в классе Service
.
Вот код. У меня есть 3 проекта:
- Инфраструктура (Данные) - ссылки на Core и EFCore
- Core (бизнес-логика) - без зависимостей
- Web API (проект MVC) - ссылается на Core, Data и EFCore
- Core (без зависимостей, даже не ссылка на 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;
}
}
- веб-API:
[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);
}
}