Skip to content

govorovvs/Quarks.DataAccess.EntityFramework

Repository files navigation

Quarks.DataAccess.EntityFramework

Version

Example

Here is an example that describes how to use EntityFramework with Quarks.Transactions.

public class User : IEntity, IAggregate
{
	public int Id { get; set; }
	public string Name { get; set; }
}

public class UserManagementDbContext()
{
	public UserManagementDbContext(string connectionString) : base(connectionString)
	{
	}

	public DbSet<User> Users { get; set; }
}

public class UserManagementDbContextManager(string connectionString) : IEfContextManager<UserManagementDbContext>
{
	private readonly string _connectionString = connectionString;

	public UserManagementDbContext CreateContext() => new UserManagementDbContext(_connectionString);
	
	public int GetHashCode() => _connectionString.GetHashCode();
}

public class EfUserRepository : EfRepository<UserManagementDbContext>, IUserRepository
{
	public NhUserRepository(UserManagementDbContextManager manager) : base(manager) { }

	public User FindById(int id) => Context.Users.SingleOrDefault(x => x.Id == id);

	public void Modify(User user) => Context.Users.Update(user);
}

public class RenameUserCommandHandler : ICommandHandler<RenameUserCommand>
{
	private readonly IUserRepository _userRepository;

	public async Task HandleAsync(RenameUserCommand command, CancellationToken ct)
	{
		using(ITransaction transaction = Transaction.BeginTransaction())
		{
			User user = _userRepository.FindById(command.Id);
			user.Name = command.Name;
			_userRepository.Modify(user);
			await transaction.CommitAsync(ct);
		}
	}
}

How it works

EfRepository internally uses EfTransaction and gets it from the current Quarks.Transaction.

public abstract class EfRepository<TDbContext>(IEfContextManager<TDbContext> contextManager)
{
	private readonly IEfContextManager<TDbContext> _contextManager = contextManager;

	protected TDbContext Context => Transaction.Context;
	
	private EfTransaction Transaction => EfTransaction.GetCurrent(_contextManager);
}

internal class EfTransaction<TDbContext>(TDbContext context) : IDependentTransaction
{
	public TDbContext Context { get; } = context;
}

internal static class EfTransaction
{
	public static EfTransaction<TDbContext> GetCurrent<TDbContext>(IEfContextManager<TDbContext> contextManager)
	{
		int key = contextManager.GetHashCode().ToString();
		IDependentTransaction current;
		if (!Transaction.Current.DependentTransactions.TryGetValue(key, out current))
		{
			current = new EfTransaction<TDbContext>(contextManager.CreateContext());
			Transaction.Current.Enlist(key, current);
		}

		return (EfTransaction<TDbContext>)current;
	}
}

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published