Implemented basic unit of work.

pull/81/head
Halil İbrahim Kalkan 9 years ago
parent d3c613d121
commit dcbb625d88

@ -1,4 +1,5 @@
using AbpDesk.Tickets.Dtos;
using System.Threading.Tasks;
using AbpDesk.Tickets.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Application.Services.Dtos;
@ -6,6 +7,6 @@ namespace AbpDesk.Tickets
{
public interface ITicketAppService : IApplicationService
{
ListResultDto<TicketDto> GetAll(GetAllTicketsInput input);
Task<ListResultDto<TicketDto>> GetAll(GetAllTicketsInput input);
}
}

@ -1,8 +1,10 @@
using System.Linq;
using System.Threading.Tasks;
using AbpDesk.Tickets.Dtos;
using Volo.Abp.Application.Services.Dtos;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Linq.Extensions;
using Volo.Abp.Uow;
using Volo.ExtensionMethods;
namespace AbpDesk.Tickets
@ -10,22 +12,32 @@ namespace AbpDesk.Tickets
public class TicketAppService : ITicketAppService
{
private readonly IQueryableRepository<Ticket, int> _ticketRepository;
private readonly IUnitOfWorkManager _unitOfWorkManager;
public TicketAppService(IQueryableRepository<Ticket, int> ticketRepository)
public TicketAppService(
IQueryableRepository<Ticket, int> ticketRepository,
IUnitOfWorkManager unitOfWorkManager
)
{
_ticketRepository = ticketRepository;
_unitOfWorkManager = unitOfWorkManager;
}
public ListResultDto<TicketDto> GetAll(GetAllTicketsInput input)
public async Task<ListResultDto<TicketDto>> GetAll(GetAllTicketsInput input)
{
var tickets = _ticketRepository
.WhereIf(
!input.Filter.IsNullOrWhiteSpace(),
t => t.Title.Contains(input.Filter) || t.Body.Contains(input.Filter)
).Select(t => new TicketDto { Id = t.Id, Title = t.Title, Body = t.Body })
.ToList();
using (var unitOfWork = _unitOfWorkManager.Begin())
{
var tickets = _ticketRepository
.WhereIf(
!input.Filter.IsNullOrWhiteSpace(),
t => t.Title.Contains(input.Filter) || t.Body.Contains(input.Filter)
).Select(t => new TicketDto { Id = t.Id, Title = t.Title, Body = t.Body })
.ToList();
return new ListResultDto<TicketDto>(tickets);
await unitOfWork.CompleteAsync();
return new ListResultDto<TicketDto>(tickets);
}
}
}
}

@ -1,6 +1,7 @@
using System;
using AbpDesk.Tickets;
using AbpDesk.Tickets.Dtos;
using Volo.Abp.Threading;
using Volo.DependencyInjection;
namespace AbpDesk.ConsoleDemo
@ -16,7 +17,7 @@ namespace AbpDesk.ConsoleDemo
public void List()
{
var result = _ticketAppService.GetAll(new GetAllTicketsInput());
var result = AsyncHelper.RunSync(() => _ticketAppService.GetAll(new GetAllTicketsInput()));
foreach (var ticket in result.Items)
{

@ -1,4 +1,5 @@
using AbpDesk.Models.Tickets;
using System.Threading.Tasks;
using AbpDesk.Models.Tickets;
using AbpDesk.Tickets;
using AbpDesk.Tickets.Dtos;
using Microsoft.AspNetCore.Mvc;
@ -15,9 +16,9 @@ namespace AbpDesk.Controllers
_ticketAppService = ticketAppService;
}
public IActionResult Index(GetAllTicketsInput input)
public async Task<IActionResult> Index(GetAllTicketsInput input)
{
var result = _ticketAppService.GetAll(input);
var result = await _ticketAppService.GetAll(input);
var model = new IndexViewModel
{

@ -1,31 +1,65 @@
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Data;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.Uow;
namespace Volo.Abp.Repositories.EntityFrameworkCore
{
public class UnitOfWorkDbContextProvider<TDbContext> : IDbContextProvider<TDbContext>
public class UnitOfWorkDbContextProvider<TDbContext> : IDbContextProvider<TDbContext>
where TDbContext : AbpDbContext<TDbContext>
{
private readonly TDbContext _dbContext;
private readonly IUnitOfWorkManager _unitOfWorkManager;
private readonly IConnectionStringResolver _connectionStringResolver;
public UnitOfWorkDbContextProvider(
TDbContext dbContext,
IUnitOfWorkManager unitOfWorkManager) //TODO: Should create this dynamically inside a unit of work.
IUnitOfWorkManager unitOfWorkManager,
IConnectionStringResolver connectionStringResolver)
{
_dbContext = dbContext;
_unitOfWorkManager = unitOfWorkManager;
_connectionStringResolver = connectionStringResolver;
}
public TDbContext GetDbContext()
{
//if (_unitOfWorkManager.Current == null)
//{
// throw new AbpException("A DbContext can only be created inside a unit of work!");
//}
var unitOfWork = _unitOfWorkManager.Current;
if (unitOfWork == null)
{
throw new AbpException("A DbContext can only be created inside a unit of work!");
}
var moduleName = "";//TODO: Get module name from DbContext?
var dbContextKey = $"{moduleName}_{typeof(TDbContext).FullName}_{_connectionStringResolver.Resolve(moduleName)}";
var databaseApi = unitOfWork.GetOrAddDatabaseApi(
dbContextKey,
() => new DbContextDatabaseApi<TDbContext>(
unitOfWork.ServiceProvider.GetRequiredService<TDbContext>()
));
return ((DbContextDatabaseApi<TDbContext>)databaseApi).DbContext;
}
}
public class DbContextDatabaseApi<TDbContext> : IDatabaseApi
where TDbContext : AbpDbContext<TDbContext>
{
public TDbContext DbContext { get; }
return _dbContext;
public DbContextDatabaseApi(TDbContext dbContext)
{
DbContext = dbContext;
}
public Task SaveChangesAsync()
{
return DbContext.SaveChangesAsync();
}
public Task CommitAsync()
{
return DbContext.SaveChangesAsync();
}
}
}

@ -5,11 +5,11 @@ using Volo.ExtensionMethods.Collections.Generic;
namespace Volo.Abp.Data
{
public class ConnectionStringResolver : IConnectionStringResolver, ITransientDependency
public class DefaultConnectionStringResolver : IConnectionStringResolver, ITransientDependency
{
private readonly DbConnectionOptions _options; //TODO: Use IOptionsSnapshot
private readonly DbConnectionOptions _options; //TODO: Use IOptionsSnapshot?
public ConnectionStringResolver(IOptions<DbConnectionOptions> options)
public DefaultConnectionStringResolver(IOptions<DbConnectionOptions> options)
{
_options = options.Value;
}

@ -1,3 +1,4 @@
using System;
using System.Threading.Tasks;
using JetBrains.Annotations;
@ -5,6 +6,8 @@ namespace Volo.Abp.Uow
{
internal class ChildUnitOfWork : IUnitOfWork
{
public IServiceProvider ServiceProvider => _parent.ServiceProvider;
private readonly IUnitOfWork _parent;
public ChildUnitOfWork([NotNull] IUnitOfWork parent)
@ -23,6 +26,21 @@ namespace Volo.Abp.Uow
{
return Task.CompletedTask;
}
public IDatabaseApi FindDatabaseApi(string id)
{
return _parent.FindDatabaseApi(id);
}
public IDatabaseApi GetOrAddDatabaseApi(string id, Func<IDatabaseApi> factory)
{
return _parent.GetOrAddDatabaseApi(id, factory);
}
public IDatabaseApi AddDatabaseApi(string id, IDatabaseApi databaseApi)
{
return _parent.AddDatabaseApi(id, databaseApi);
}
public void Dispose()
{

@ -1,11 +1,20 @@
using System;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Volo.DependencyInjection;
namespace Volo.Abp.Uow
{
public interface IUnitOfWork : IDisposable, ITransientDependency
public interface IUnitOfWork : IDisposable, IServiceProviderAccessor, ITransientDependency
{
[CanBeNull]
IDatabaseApi FindDatabaseApi([NotNull] string id);
[NotNull]
IDatabaseApi GetOrAddDatabaseApi(string id, Func<IDatabaseApi> factory);
IDatabaseApi AddDatabaseApi(string id, IDatabaseApi databaseApi);
Task SaveChangesAsync();
Task CompleteAsync();

@ -1,4 +1,6 @@
namespace Volo.Abp.Uow
using System.Threading.Tasks;
namespace Volo.Abp.Uow
{
public interface IUnitOfWorkManager
{
@ -6,4 +8,11 @@
IUnitOfWork Begin();
}
public interface IDatabaseApi
{
Task SaveChangesAsync();
Task CommitAsync();
}
}

@ -1,23 +1,68 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.ExtensionMethods.Collections.Generic;
namespace Volo.Abp.Uow
{
public class UnitOfWork : IUnitOfWork
{
public IServiceProvider ServiceProvider { get; }
private readonly Dictionary<string, IDatabaseApi> _databaseApis;
public UnitOfWork(IServiceProvider serviceProvider)
{
ServiceProvider = serviceProvider;
_databaseApis = new Dictionary<string, IDatabaseApi>();
}
public void Dispose()
{
throw new NotImplementedException();
//TODO: Remove itself from IUnitOfWorkManager
}
public async Task SaveChangesAsync()
{
foreach (var databaseApi in _databaseApis.Values)
{
await databaseApi.SaveChangesAsync();
}
}
public Task SaveChangesAsync()
public async Task CompleteAsync()
{
throw new NotImplementedException();
foreach (var databaseApi in _databaseApis.Values)
{
await databaseApi.CommitAsync();
}
}
public Task CompleteAsync()
public IDatabaseApi FindDatabaseApi(string id)
{
throw new NotImplementedException();
return _databaseApis.GetOrDefault(id);
}
public IDatabaseApi GetOrAddDatabaseApi(string id, Func<IDatabaseApi> factory)
{
Check.NotNull(id, nameof(id));
Check.NotNull(factory, nameof(factory));
return _databaseApis.GetOrAdd(id, factory);
}
public IDatabaseApi AddDatabaseApi(string id, IDatabaseApi databaseApi)
{
Check.NotNull(id, nameof(id));
Check.NotNull(databaseApi, nameof(databaseApi));
if (_databaseApis.ContainsKey(id))
{
throw new AbpException($"There is already a database api with same id: {id}");
}
return _databaseApis[id] = databaseApi;
}
}
}

@ -1,4 +1,5 @@
using AbpDesk.Tickets.Dtos;
using System.Threading.Tasks;
using AbpDesk.Tickets.Dtos;
using Microsoft.Extensions.DependencyInjection;
using Shouldly;
using Xunit;
@ -15,11 +16,11 @@ namespace AbpDesk.Tickets
}
[Fact]
public void GetAll_Test()
public async Task GetAll_Test()
{
//Act
var result = _ticketAppService.GetAll(new GetAllTicketsInput());
var result = await _ticketAppService.GetAll(new GetAllTicketsInput());
//Assert
@ -27,11 +28,11 @@ namespace AbpDesk.Tickets
}
[Fact]
public void GetAll_Filtered_Test()
public async Task GetAll_Filtered_Test()
{
//Act
var result = _ticketAppService.GetAll(new GetAllTicketsInput { Filter = "non-existing-text" });
var result = await _ticketAppService.GetAll(new GetAllTicketsInput { Filter = "non-existing-text" });
//Assert

Loading…
Cancel
Save