How do I inject my dbContext class using Unity? I can't just create a Interface like for my other "normal" classes? What should I do with my RequestContext class and what should my UnityConfig look like?
public class RequestContext : IdentityDbContext<User>
{
public RequestContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
Database.SetInitializer<RequestContext>(new CreateDatabaseIfNotExists<RequestContext>());
}
public DbSet<Request> Requests { get; set; }
public DbSet<Record> Records { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
base.OnModelCreating(modelBuilder);
}
public static RequestContext Create()
{
return new RequestContext();
}
}
In my Repository class i use it like this but want to inject instead:
private RequestContext dbContext;
private IUserRepository _userRepository;
public RequestRepository(IUserRepository userRepository)
{
dbContext = new RequestContext();
_userRepository = userRepository;
}
I'm usually solving this with a DbContextFactory. This would allow you to create the context when needed and also dispose it when you're done.
public interface IDbContextFactory
{
IdentityDbContext<User> GetContext();
}
public class DbContextFactory : IDbContextFactory
{
private readonly IdentityDbContext<User> _context;
public DbContextFactory()
{
_context = new RequestContext("ConnectionStringName");
}
public IdentityDbContext<User> GetContext()
{
return _context;
}
}
This factory can easily be injected. You can see a more complete example here: Repository Pattern universal application
With the factory you will also have the option to create the DbContext in constructor or in the method. When using Unity I recommend you to do as little as possible in the constructor, as Unity will resolve the entire chain for you. This means that the DbContext will be created every time the repository is resolved. This would require the class that injects the repository also needs to dispose the repository (which in turn should dispose the DbContext), and what happens when two classes are using the same repository instance? This can obviously be solved with lifetimemanagers and good programming practices, but I find it more elegant to simply open and close the context when needed.
Example for usage in a method:
using (var context = _dbContextFactory.GenerateContext())
{
return context.Requests.FirstOrDefault(x => x.Id == foo);
}
And a more complete example for your repository:
public class RequestRepository
{
private IDbContextFactory _contextFactory;
public RequestRepository(IDbContextFactory contextFactory)
{
// DbContext will not be created in constructor, and therefore your repository doesn't have to implement IDisposable.
_contextFactory= contextFactory;
}
public Request FindById(int id)
{
// Context will be properly disposed thanks to using.
using (var context = _dbContextFactory.GenerateContext())
{
return context.Requests.FirstOrDefault(x => x.Id == id);
}
}
}
And when you're creating your interface for your context I can also recommend you to change DbSet<T> to IDbSet<T> to allow easier unit testing. Example of interface for DbContext.
public interface IDbContext : IDisposable, IObjectContextAdapter
{
IDbSet<Request> Requests { get; set; }
IDbSet<Record> Records { get; set; }
int SaveChanges();
DbSet Set(Type entityType);
DbSet<TEntity> Set<TEntity>() where TEntity : class;
}
If your're looking to inject the DbContext in the constructor you could also take a look at the Unit of Work-pattern, which wraps the DbContext and allows several classes to use the same context over a specific lifetime (eg a request). One may argue that EF already implements the Unit of Work-pattern, but I leave that discussion for another time. Here's a couple of examples:
http://www.codeproject.com/Articles/741207/Repository-with-Unit-of-Work-IoC-and-Unit-Test
Onion Architecture, Unit of Work and a generic Repository pattern
This site has a GREAT tutorial on how to get Unity working: https://medium.com/aeturnuminc/repository-pattern-with-dependency-injection-mvc-ef-code-first-91344413ba1c
I'm going to assume you have Entity Framework installed, know how to create a viewmodel and put on attributes using System.ComponentModel.DataAnnotations and System.ComponentModel.DataAnnotations.Schema namespaces, and I'll assume you can create a view and controller. None of that is really relevant until the end, anyway.
You have to get the NuGet package Unity to install these references:
Microsoft.Practices.Unity
Unity.Mvc3 (or 4 or 5)
My DataContext (Model1.cs) looks like this:
public partial class Model1 : DbContext
{
public Model1()
: this(true)
{ }
public Model1(bool enableLazyLoading = true)
: base("name=Model1")
{
// You can do this....
//Database.SetInitializer<Model1>(new CreateDatabaseIfNotExists<Model1>());
//this.Configuration.LazyLoadingEnabled = false;
// or this...
Database.SetInitializer<Model1>(null);
this.Configuration.ProxyCreationEnabled = false;
((IObjectContextAdapter)this).ObjectContext.ContextOptions.ProxyCreationEnabled = enableLazyLoading;
((IObjectContextAdapter)this).ObjectContext.ContextOptions.LazyLoadingEnabled = enableLazyLoading;
}
// All my tables and views are assigned to models, here...
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
base.OnModelCreating(modelBuilder);
}
}
My Repository (DataRepository.cs) looks like this:
namespace WeeklyReport.Repository
{
public class DataRepository : IDataRepository
{
private bool disposing;
private readonly Model1 context;
public virtual void Dispose()
{
if (disposing)
{
return;
}
disposing = true;
if (context != null)
{
context.Dispose();
}
}
public void SaveChanges()
{
context.SaveChanges();
}
public DataRepository()
{
context = new Model1();
context.Configuration.ProxyCreationEnabled = false;
}
public IEnumerable<ReportViewModel> GetAllMetrics()
{
var myMetrics = context.MetricsTable; // put into ReportVM and return, etc.
}
// etc., etc.
}
}
My Interface (IDataRepository.cs) looks like this:
namespace WeeklyReport.Repository
{
public interface IDataRepository
{
void SaveChanges();
IEnumerable<ReportViewModel> GetAllMetrics();
}
}
My UnityConfig.cs in the App_Start folder looks like this:
using Microsoft.Practices.Unity;
using WeeklyReport.Repository;
using System.Web.Mvc;
using Unity.Mvc3;
namespace WeeklyReport
{
public class UnityConfig
{
public static void RegisterContainer()
{
var container = new UnityContainer();
//ensure the repository is disposed after each request by using the lifetime manager
container.RegisterType<IDataRepository, DataRepository>(new HierarchicalLifetimeManager());
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
}
}
And you have to call RegisterContainer in Global.ascx.cs inside Application_Start:
UnityConfig.RegisterContainer();
From a controller, it gets a handle to IDataRepository:
using WeeklyReport.Repository;
namespace WeeklyReport.Controllers
{
public class ReportController : Controller
{
private readonly IDataRepository repository;
public ReportController(IDataRepository repository)
{
this.repository = repository;
}
public ActionResult Index()
{
List<ReportViewModel> reportVM = new List<ReportViewModel>();
var reqs = repository.GetAllMetrics();
// iterate reqs and put into reportVM, etc.
return View(reportVM);
}
}
}
And you can call repository as if it was the real class - you're just getting an interface instance to it.
I'm solving this problem with DbContext.Set<TEntity>() method, DbContext wrapper class and generics.
I have IRepositoryContext interface and RepositoryContext to wrap my DbContext:
public interface IRepositoryContext
{
DbContext DbContext { get; }
/// <summary>
/// Commit data.
/// </summary>
void Save();
}
public class RepositoryContext : IRepositoryContext
{
private readonly DbContext _dbContext;
public RepositoryContext(DbContext dbContext)
{
_dbContext = dbContext;
}
public DbContext DbContext { get { return _dbContext; } }
public void Save()
{
_dbContext.SaveChanges();
}
}
Ok, then I write bas implementation of generic repository:
public abstract class RepositoryBase<TEntity, TId> : IRepository<TEntity, TId>
where TEntity : class , IEntity<TId>, IRetrievableEntity<TEntity, TId>
where TId : struct
{
protected readonly IRepositoryContext RepositoryContext;
protected readonly DbContext Context;
protected RepositoryBase(IRepositoryContext repositoryContext)
{
RepositoryContext = repositoryContext;
}
public DbSet<TEntity> Data { get { return RepositoryContext.DbContext.Set<TEntity>(); }
public TEntity Get(TId id)
{
return Data.Find(id);
}
public virtual IList<TEntity> GetAll()
{
return Data.ToList();
}
public virtual TEntity Save(TEntity entity)
{
try
{
var state = entity.Id.Equals(default(TId)) ? EntityState.Added : EntityState.Modified;
RepositoryContext.DbContext.Entry(entity).State = state;
RepositoryContext.Save();
return entity;
}
catch (DbEntityValidationException e)
{
throw ValidationExceptionFactory.GetException(e);
}
}
public virtual void Delete(TEntity entity)
{
if (entity == null) return;
Data.Remove(entity);
Context.SaveChanges();
}
public void Commit()
{
RepositoryContext.Save();
}
public IList<TEntity> Get(Expression<Func<TEntity, bool>> criteria)
{
return Data.Where(criteria).ToList();
}
// some other base stuff here
}
Ok, now I can register my DbContext with next extension methods:
public static class RikropCoreDataUnityExtensions
{
#region Const
private readonly static Type _repositoryInterfaceType = typeof(IRepository<,>);
private readonly static Type _deactivatableRepositoryInterfaceType = typeof(IDeactivatableRepository<,>);
private readonly static Type _deactivatableEntityType = typeof(DeactivatableEntity<>);
private readonly static Type _retrievableEntityType = typeof(IRetrievableEntity<,>);
#endregion Const
#region public methods
/// <summary>
/// Register wrapper class.
/// </summary>
/// <typeparam name="TContext">DbContext type.</typeparam>
/// <param name="container">Unity-container.</param>
public static void RegisterRepositoryContext<TContext>(this IUnityContainer container)
where TContext : DbContext, new()
{
container.RegisterType<IRepositoryContext, RepositoryContext>(new InjectionFactory(c => new RepositoryContext(new TContext())));
}
/// <summary>
/// Register wrapper class.
/// </summary>
/// <typeparam name="TContext">DbContext type.</typeparam>
/// <param name="container">Unity-container.</param>
/// <param name="contextConstructor">DbContext constructor.</param>
/// <param name="connectionString">Connection string name.</param>
public static void RegisterRepositoryContext<TContext>(this IUnityContainer container,
Func<string, TContext> contextConstructor, string connectionString)
where TContext : DbContext
{
container.RegisterType<IRepositoryContext, RepositoryContext>(
new InjectionFactory(c => new RepositoryContext(contextConstructor(connectionString))));
}
/// <summary>
/// Automatically generation and registration for generic repository marked by attribute.
/// </summary>
/// <param name="container">Unity-container.</param>
/// <param name="assembly">Assembly with repositories marked with RepositoryAttribute.</param>
public static void RegisterCustomRepositories(this IUnityContainer container, Assembly assembly)
{
foreach (var repositoryType in assembly.GetTypes().Where(type => type.IsClass))
{
var repositoryAttribute = repositoryType.GetCustomAttribute<RepositoryAttribute>();
if (repositoryAttribute != null)
{
container.RegisterType(
repositoryAttribute.RepositoryInterfaceType,
repositoryType,
new TransientLifetimeManager());
}
}
}
/// <summary>
/// Automatically generation and registration for generic repository for all entities.
/// </summary>
/// <param name="container">Unity-container.</param>
/// <param name="assembly">Assembly with Entities which implements IRetrievableEntity.</param>
public static void RegisterRepositories(this IUnityContainer container, Assembly assembly)
{
foreach (var entityType in assembly.GetTypes().Where(type => type.IsClass))
{
if (!entityType.InheritsFromGeneric(_retrievableEntityType))
continue;
Type[] typeArgs = entityType.GetGenericTypeArguments(_retrievableEntityType);
Type constructedRepositoryInterfaceType = _repositoryInterfaceType.MakeGenericType(typeArgs);
container.RegisterRepository(constructedRepositoryInterfaceType);
if (entityType.InheritsFrom(_deactivatableEntityType.MakeGenericType(new[] { typeArgs[1] })))
{
var constructedDeactivatableRepositoryInterfaceType =
_deactivatableRepositoryInterfaceType.MakeGenericType(typeArgs);
container.RegisterRepository(constructedDeactivatableRepositoryInterfaceType);
}
}
}
#endregion public methods
#region private methods
/// <summary>
/// Generate and register repository.
/// </summary>
/// <param name="container">Unity-container.</param>
/// <param name="repositoryInterfaceType">Repository interface type.</param>
private static void RegisterRepository(this IUnityContainer container, Type repositoryInterfaceType)
{
var factoryGenerator = new RepositoryGenerator();
var concreteFactoryType = factoryGenerator.Generate(repositoryInterfaceType);
container.RegisterType(
repositoryInterfaceType,
new TransientLifetimeManager(),
new InjectionFactory(
c =>
{
var activator = new RepositoryActivator();
return activator.CreateInstance(c, concreteFactoryType);
}));
}
#endregion private methods
}
Finally you can just resolve IRepository<EntityType> on your classes. You just need to register your RepositoryContext:
container.RegisterRepositoryContext<MyDbContext>();
//container.RegisterRepositoryContext(s => new MyDbContext(s), "myConStr");
And your repository will resolve IRepositoryContext and you can have access to DbSet<TEntity> and other DbContext members via IRepositoryContext property.
You can use full source code for repositories, Unity-helpers on Github.
Related
I am trying to create a Repository & UnitOfWork for Data Access Layer. In my current implementation I have to modify my UnitOfWork everytime I create a new repository. I would like to avoid that and also keep the functionality to extend my repository abstract class.
Following is my generic Repository & UnitOfWork interface & classes
public interface IRepositoryBase<T> where T : class
{
IList<T> FindAll();
T FindByCondition(Expression<Func<T, bool>> expression);
void Create(T entity);
void Update(T entity);
void Delete(T entity);
}
public abstract class RepositoryBase<T> : IRepositoryBase<T> where T : class
{
protected DBContext _dbContext { get; set; }
public RepositoryBase(DBContext dbContext)
{
_dbContext = dbContext;
}
//other methods removed
public void Create(T entity)
{
_dbContext.Set<T>().Add(entity);
}
}
public interface IUnitOfWork
{
IReminderRepository Reminder { get; }
void Save();
}
public class UnitOfWork : IUnitOfWork, IDisposable
{
protected DBContext _dbContext { get; set; }
private IReminderRepository _reminderRepository;
public UnitOfWork(DBContext dbContext)
{
_dbContext = dbContext;
}
public IReminderRepository Reminder
{
get
{
return _reminderRepository = _reminderRepository ?? new ReminderRepository(_dbContext);
}
}
public void Save()
{
_dbContext.SaveChanges();
}
public void Dispose()
{
_dbContext.Dispose();
}
}
Here I can extend my Repository as per my specific needs by implementing the specific Repository as
public interface IReminderRepository : IRepositoryBase<Reminder>
{
IList<Reminder> GetAllReminders();
Reminder GetReminderById(Guid id);
Reminder GetReminderByName(string name);
void CreateReminder(Reminder reminder);
void UpdateReminder(Reminder reminder);
void DeleteReminder(Reminder reminder);
}
public class ReminderRepository : RepositoryBase<Reminder>, IReminderRepository
{
public ReminderRepository(DBContext dbContext)
: base(dbContext)
{
_dbContext = dbContext;
}
//other methods removed
public Reminder GetReminderByName(string name)
{
return FindAll()
.OrderByDescending(r => r.Name)
.FirstOrDefault(r => r.Name == name);
//return FindByCondition(r => r.Name == name);
}
}
This is ok but when ever I will create a new Specific Repository I will have to modify the UnitOfWork class as well by adding a new property for the new Repository.
While searching online I found following but it does not work in my case as my RepositoryBase is an abstract class.
public interface IUnitOfWork
{
void Save();
}
public class UnitOfWork : IUnitOfWork, IDisposable
{
private readonly DBContext _dbContext { get; set; }
private readonly Dictionary<Type, object> _repositories = new Dictionary<Type, object>();
public Dictionary<Type, object> Repositories
{
get { return _repositories; }
set { Repositories = value; }
}
public UnitOfWork(DBContext dbContext)
{
_dbContext = dbContext;
}
public IRepositoryBase<T> Repository<T>() where T : class
{
if (Repositories.Keys.Contains(typeof(T)))
{
return Repositories[typeof(T)] as IRepositoryBase<T>;
}
IRepositoryBase<T> repo = new RepositoryBase<T>(_dbContext);//This does not work
Repositories.Add(typeof(T), repo);
return repo;
}
public void Save()
{
_dbContext.SaveChanges();
}
}
You obviously need to get a reference to a IReminderRepository somewhere in your code to be able to use the remainder specific APIs.
If you don't want to extend your UnitOfWork class to return an IReminderRepository, you may create one yourself in the method that actually uses the specific repository, e.g.:
using (var context = new DBContext())
{
IUnitOfWork uow = new UnitOfWork(context);
ReminderRepository repository = new ReminderRepository(context);
Reminder remainder = repository.GetReminderByName("...");
remainder.SomeProperty = "updated value..";
uow.Save();
}
The only purpose of using the unit of work is to be able to share the same context between several different repositories anyway. Exposing a Dictionary<Type, object> in your UnitOfWork won't solve anything as the purpose of using generics is to provide compile-time type safety.
I am trying to implement UOW with repository pattern in my application.
While the independent repository is in place, but while multiple repositories in one transaction (UOW) is driving me crazy.
EF Relation One Customer - Many CustomerContacts
IUnitOfWork
public interface IUnitOfWork
: IDisposable
{
void InitTransaction();
void Rollback();
void CommitTransaction();
}
BaseUOW
public class UnitOfWork :
IUnitOfWork
{
protected DbContextTransaction _transaction;
#region IUnitOfWork
public void CommitTransaction()
{
_transaction.UnderlyingTransaction.Commit();
}
public void Rollback()
{
_transaction.UnderlyingTransaction.Rollback();
}
#endregion IUnitOfWork
}
CustomerUOW
public class CustomerUOW
: UnitOfWork
{
private IRepository<CustomerRepository> _customerRepository;
private IRepository<CustomerContactRepository> _customerContactRepository;
public BranchUOW(IRepository<CustomerRepository> customerRepository,
IRepository<CustomerContactRepository> customerContactRepository)
{
_customerRepository= customerRepository;
_customerContactRepository= customerContactRepository;
}
public override void InitTransaction()
{
_transaction.Commit();
}
}
How do I implement my CustomerUOW so that Customer &
CustomerContact repository share the same DbContext & goes in one
transaction??
Note: Each repository has an implementation of CRUD in their separate class. like
public class EntityRepository<C, T>
: BaseRepository<FoodieTenantContext, T>
where T : class
where C : CustomerContext
{
private DbSet<T> _dataSet
{
get
{
return _ctx.Set<T>();
}
}
public EntityRepository(FoodieTenantContext ctx)
: base(ctx)
{
}
public override void Add(T entity)
{
_dataSet.Add(entity);
}
public override void Delete(T entity)
{
throw new NotImplementedException();
}
public override IEnumerable<T> Find(Expression<Func<T, bool>> predicate)
{
return _dataSet.Where(predicate).ToList<T>();
}
public override IEnumerable<T> GetAll()
{
return _dataSet.ToList<T>();
}
public override IQueryable<T> GetQuery()
{
return _dataSet;
}
public override int Save()
{
return _ctx.SaveChanges();
}
public override T Single(Expression<Func<T, bool>> predicate)
{
return _dataSet.Where(predicate).SingleOrDefault();
}
public override void Update(T entity)
{
_dataSet.Attach(entity);
_ctx.Entry<T>(entity).State = EntityState.Modified;
}
}
Thanks
On way would be to provide a Func<FoodieTenantContext, IRepository<CustomerContactRepository>> in your CustomerUow
public abstract class UnitOfWork : IUnitOfWork
{
public UnitOfWork(FoodieTenantContext context)
{
this.Context = context;
}
// ... rest of the class
}
// usage could be like the following
public class CustomerUOW : UnitOfWork
{
public CustomerService(Func<FoodieTenantContext, IRepository<CustomerRepository>> customerRepo
, Func<FoodieTenantContext, IRepository<CustomerContactRepository>> contactRepo
, FoodieTenantContext context)
: (context)
{
_customerRepo = customerRepo(context);
_contactRepo = contactRepo(context);
}
}
Another option would be to create a RepositoryFactory, but this would mean you would have to expose a Context property from IRepository<T>
public class RepositoryFactory
{
IServiceProvider _ioc; // This would be your IoC/DI Container
public RepositoryFactory(IServiceProvider ioc)
{
_ioc = ioc;
}
// Resolve T passing in the provided `FoodieTenantContext` into the constructor
public IRepository<T> CreateRepository<T>(FoodieTenantContext context) =>
_ioc.Resolve<T>(context);
}
Another solution could be (my least favourite) would be to expose methods in a RepositoryFactory for each type of IRepository<T>
public class RepositoryFactory
{
public IRepository CreateCustomerContactRepository(FoodieTenantContext context) =>
return new CustomerContactRepository(context);
}
Registering Func in Castle.Windsor
As per comment, to register Func<T> in Castle.Windsor you can try something like the following which is a modified version of Anton's answer to Func injecting with Windsor container question.. (I am not able to test this right now)
Container.Register(
Component.For<Func<FoodieTenantContext, IRepository<CustomerRepository>>>()
.Instance((FoodieTenantContext context) => Container.Resolve<IRepository<CustomerRepository>>(new {context = context}))
)
Otherwise you could try playing around with AsFactory(). For more info read Windsor documentation
And as a last resort, you can always fallback to manually creating a factory or switching IoC/DI containers that support Func<[TIn1, TIn2, ...], T> out of the box, or at least natively.
I have an MVC 5 application that uses EF 6 and implements Repository pattern with dependency injection using the DI container Ninject. The connection string for the dbcontext is stored in the Web.config file which the EF Context properly finds. Everything works fine. Lately, I have a requirement that the connection to my DBContext need to be determined at runtime and connect to different databases (but with exactly the same structure). So, I need to change the sql connectionstring part from the entity connectionstring at run-time before the repository is instantiated. I would really appreciate some help in doing it. I am not a DI guru; know just enough Ninject to get my things going.
Here is my Repository Base Interface:
public interface IRepositoryBase<T> where T : class
{
void Add(T entity, string userGuid = "");
void Delete(T entity);
// ... removed other method signatures for brevity
}
My Repository base implementation:
public abstract class RepositoryBase<D, T> : IRepositoryBase<T>, IDisposable
where T : class
where D : DbContext, new()
{
private Guid? currUserGuid = null;
private D dataContext;
protected D DataContext
{
get
{
if (dataContext == null)
dataContext = new D();
return dataContext;
}
set { dataContext = value; }
}
public IQueryable<T> FindBy(Expression<Func<T, bool>> predicate)
{
return DataContext.Set<T>().Where(predicate);
}
public virtual IQueryable<T> GetAll()
{
IQueryable<T> query = DataContext.Set<T>();
return query;
}
public virtual void Delete(T entity)
{
OperationStatus stat = TryDelete(entity);
}
// .... removed rest for brevity
}
Interface and implementation for concrete class:
public interface ICustomerRepository : IRepositoryBase<Customer>
{
Customer GetCustomerAndStatus( Guid custGuid );
}
public class CustomerRepository : RepositoryBase<PCDataEFContext, Customer>, ICustomerRepository
{
public Customer GetCustomerAndStatus( Guid custGuid )
{
return DataContext.Customers.Include( x => x.CustStatusType )
.SingleOrDefault( x => x.PKGuid == custGuid );
}
}
My Ninject dependency resolver:
public class NinjectDependencyResolver : IDependencyResolver
{
private IKernel kernel;
public NinjectDependencyResolver()
{
kernel = new StandardKernel();
AddBindings();
}
public IKernel Kernel { get { return kernel; } }
private void AddBindings()
{
kernel.Bind<ICustomerRepository>().To<CustomerRepository>();
// ... other bindings are omitted for brevity
}
}
and finally, here is my Entity Framework generated DBContext:
public partial class PCDataEFContext : DbContext
{
public PCDataEFContext()
: base("name=PCDataEFContext")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<Customer> Customers { get; set; }
}
All the above code works great! But as I said in the beginning, I don't know how to inject the connection string into my Repositorybase class at runtime so that I don't have to modify any of my inherited repositories (I have plenty of them). Someone please help.
Babu.
Could you do it like this?
public partial class PCDataEFContext : DbContext
{
public PCDataEFContext()
: base(Util.GetTheConnectionString())
{ }
}
public class MyDerivedContext : PCDataEFContext
{
public MyDerivedContext()
: base()
{ }
}
class Util
{
public static string GetTheConnectionString()
{
// return the correct name based on some logic...
return "name=PCDataEFContext";
}
}
Another way of doing it, could be in the RepositorBase class you defined, by altering the connectionstring after the creation of the dbcontext:
protected D DataContext
{
get
{
if (dataContext == null)
{
dataContext = new D();
dataContext.Database.Connection.ConnectionString = "the new connectionstring";
}
return dataContext;
}
set { dataContext = value; }
}
I'm using CQRS pattern in my recent project, and used EF code first in my DAL, so I defined some generic CommandHandlers to do Insert/Update/Delete:
public class InsertCommandHandler<TEntity> : ICommandHandler<InsertCommandParameter<TEntity>>
where TEntity : BaseEntity, IAggregateRoot<TEntity>, new()
{
private readonly IUnitOfWork _uow;
public InsertCommandHandler(IUnitOfWork uow)
{
_uow = uow;
}
public void Handle(InsertCommandParameter<TEntity> parameter)
{
var entity = parameter.Entity;
_uow.Repository<TEntity>().Add(entity);
}
}
public interface ICommandParameter
{
}
public abstract class BaseEntityCommandParameter<T> : ICommandParameter
where T : BaseEntity, new()
{
public T Entity { get; set; }
protected BaseEntityCommandParameter()
{
Entity = new T();
}
}
public class InsertCommandParameter<T> : BaseEntityCommandParameter<T> where T : class, new()
{
}
As you see I injected the IUnitOfWork to the InsertCommandHandler constructor.
public interface IUnitOfWork : IDisposable
{
IRepository<T> Repository<T>() where T : BaseEntity, IAggregateRoot<T>,new ();
void Commit();
}
I used Structuremap 3 as my IoC Container, So I defined following conversion to resolve ICommandHandlers for each BaseEntity types(using custom registration conventions for partially closed types):
public class CRUDCommandRegistrationConvention : StructureMap.Graph.IRegistrationConvention
{
private static readonly
Type _openHandlerInterfaceType = typeof(ICommandHandler<>);
private static readonly
Type _openInsertCommandType = typeof(InsertCommandParameter<>);
private static readonly
Type _openInsertCommandHandlerType = typeof(InsertCommandHandler<>);
private static readonly
Type _openUpdateCommandType = typeof(UpdateCommandParameter<>);
private static readonly
Type _openUpdateCommandHandlerType = typeof(UpdateCommandHandler<>);
private static readonly
Type _openDeleteCommandType = typeof(DeleteCommandParameter<>);
private static readonly
Type _openDeleteCommandHandlerType = typeof(DeleteCommandHandler<>);
public void Process(Type type, Registry registry)
{
if (!type.IsAbstract && typeof(BaseEntity).IsAssignableFrom(type))
if (type.GetInterfaces()
.Any(x => x.IsGenericType && x.GetGenericTypeDefinition()
== typeof(IAggregateRoot<>)))
{
Type closedInsertCommandType = _openInsertCommandType.MakeGenericType(type);
Type closedInsertCommandHandlerType = _openInsertCommandHandlerType.MakeGenericType(type);
Type closedUpdateCommandType = _openUpdateCommandType.MakeGenericType(type);
Type closedUpdateCommandHandlerType = _openUpdateCommandHandlerType.MakeGenericType(type);
Type closedDeleteCommandType = _openDeleteCommandType.MakeGenericType(type);
Type closedDeleteCommandHandlerType = _openDeleteCommandHandlerType.MakeGenericType(type);
Type insertclosedHandlerInterfaceType = _openHandlerInterfaceType.MakeGenericType(closedInsertCommandType);
Type updateclosedHandlerInterfaceType = _openHandlerInterfaceType.MakeGenericType(closedUpdateCommandType);
Type deleteclosedHandlerInterfaceType = _openHandlerInterfaceType.MakeGenericType(closedDeleteCommandType);
registry.For(insertclosedHandlerInterfaceType).Use(closedInsertCommandHandlerType);
registry.For(updateclosedHandlerInterfaceType).Use(closedUpdateCommandHandlerType);
registry.For(deleteclosedHandlerInterfaceType).Use(closedDeleteCommandHandlerType);
}
}
}
And used it in my CompositionRoot:
public static class ApplicationConfiguration
{
public static IContainer Initialize()
{
ObjectFactory.Initialize(x =>
{
x.Scan(s =>
{
s.AssemblyContainingType(typeof(ICommandHandler<>));
s.AssemblyContainingType(typeof(Order));
s.AssemblyContainingType(typeof(FindOrderByIdQueryHandler));
s.WithDefaultConventions();
x.For(typeof(IUnitOfWork))
.Use(typeof(EfUnitOfWork<SaleDBContext>))
.Named("SaleDBContext")
.SetLifecycleTo((Lifecycles.Singleton));
s.Convention<CRUDCommandRegistrationConvention>();
});
});
return ObjectFactory.Container;
}
public static T Resolve<T>()
{
return ObjectFactory.GetInstance<T>();
}
}
I registered EfUnitOfWork<SaleDBContext> for IUnitOfWork, but I want to use separate DbContext per each module in my solution(Bounded context). For example my sale module has its own DbContext, HR module has its own DbContext and etc, and above registration conversion, only register EfUnitOfWork<SaleDBContext> as my IUnitOfWork.
I have some modules(Solution Folders in Visual Studio) in my solution and each module has 3 layer(3 class library projects):
My modules has following structure(each module has 3 assemblies) for example:
SaleModule:
----Application
----Domain (Entities , ...) //Order, Customer,...
----DAL (DbContext ,...) //SaleDbContext
HRModule:
----Application
----Domain (Entities , ...) // Employee, OrganizationUnit, ...
----DAL (DbContext ,...)//HRDbContext
InfrastructureModule:
----Application (ICommandHandler,IQueryHandler,...)
----Domain
----DAL
The InsertCommandHandler<T> puts in Infrastructure Module.
When I use the InsertCommanHandler<T> I want it uses corresponding module's DbContext as IUnitOfWork. for example, I want the InsertCommandHandler<Order> uses SaleDbContext as it's IUnitOfWork and InsertCommandHandler<Employee> uses HRDbContext as it's IUnitOfWork.
[UPDATED]
This is a sample of cunsumers code that IoC containar should provide SaleDbContext for Consumer1 and HRDbContext for Consumer2:
public class Consumer1
{
ICommandHandler<InsertCommandParameter<Order>> _insertCommandHandler;
public Consumer1(ICommandHandler<InsertCommandParameter<Order>> insertCommandHandler)
{
_insertCommandHandler = insertCommandHandler;
}
public void DoInsert()
{
var command = new InsertCommandParameter<Order>();
command.Entity = new Order(){
Number = 'ord-01',
// other properties
};
insertCommandHandler.Handle(command); //this query handler should use SaleDbContext
}
}
public class Consumer2
{
ICommandHandler<InsertCommandParameter<Employee>> _insertCommandHandler;
public Consumer2(ICommandHandler<InsertCommandParameter<Employee>> insertCommandHandler)
{
_insertCommandHandler = insertCommandHandler;
}
public void DoInsert()
{
var command = new InsertCommandParameter<Employee>();
command.Entity = new Employee(){
EmployeeNumber = 'Emp1',
// other properties
};
insertCommandHandler.Handle(command); //this query handler should use HRDbContext
}
}
How could I do that in my composition root using StructureMap?
You can make IUnitOfWork generic as in IUnitOfWork<TConnection>. This allows each Repository to stipulate which UnitOfWork it requires, ideally using constructor injection, e.g.
public class InsertCommandHandler : ICommandHandler<Order>
{
public InsertCommandHandler(IUnitOfWork<SalesDbContext> salesUnitOfWork)
{
// ...
}
}
However, you probably don't want to reference the DbContext in each handler so you should define an abstraction to avoid such a dependency.
Start with a simple interface that all DbContext wrapper classes will implement
public interface IConnection
{
DbContext Context { get; }
}
Update IUnitOfWork accordingly
public interface IUnitOfWork<TConnection> where TConnection : IConnection { }
Here's an example wrapper
public class SalesConnection : IConnection
{
private readonly DbContext context;
public SalesConnection()
{
this.context = new SalesDbContext();
}
public DbContext Context { get { return this.context; } }
}
And here's what the updated command handler will look like
public class InsertCommandHandler : ICommandHandler<Order>
{
public InsertCommandHandler(IUnitOfWork<SalesConnection> salesUnitOfWork)
{
// ...
}
}
UPDATE
The logical thing to do for common handlers is to have one per logical domain (i.e. per DbContext), for example SalesInsertCommandHandler, HRInsertCommandHandler
public class SalesInsertCommandHandler<TCommand> : ICommandHandler<TCommand>
{
public SalesInsertCommandHandler(IUnitOfWork<SalesConnection> unitOfWork)
{
}
}
This adheres to the separation of concerns principle and gives you extra flexibility when you come to decorate your concerns with different aspects (tracing, retry logic etc.)
All command handlers can of course inherit from a single common (abstract) command handler.
public abstract class CommandHandler<TConnection, TCommand> :
ICommandHandler<TCommand>
where TConnection : IConnection
{
private readonly IUnitOfWork<TConnection> unitOfWork;
public CommandHandler(IUnitOfWork<TConnection> unitOfWork)
{
this.unitOfWork = unitOfWork;
}
}
public class SalesInsertCommandHandler<TCommand> :
CommandHandler<SalesConnection, TCommand>
{
}
In my backend service I use unit of work pattern. I was wondering if I'm missing something related to disposing objects.
First, this is the code I have so far, which works. The service just calls a request handler:
[GlobalExceptionHandlerBehaviour(typeof(GlobalExceptionHandler))]
public class CustomerService : ICustomerService
{
public void AddCustomer(AddCustomerRequest request)
{
ObjectFactory.GetInstance<AddCustomerRequestHandler>().Execute(request);
}
}
The request handler looks like:
public class AddCustomerRequestHandler
{
private readonly IUnitOfWork _unitOfWork;
private readonly ICustomerRepository _customerRepository;
public AddCustomerRequestHandler(IUnitOfWork unitOfWork, ICustomerRepository customerRepository)
{
_unitOfWork = unitOfWork;
_customerRepository = customerRepository;
}
public void Execute(AddCustomerRequest request)
{
var customer = new Customer(request.Id, request.CompanyName);
_customerRepository.Add(customer);
_unitOfWork.Commit();
}
}
The unit of work is defined as follows:
public interface IUnitOfWork
{
void Commit();
}
public class UnitOfWork : IUnitOfWork
{
private readonly IDatabaseFactory<EfTrackerDbContext> _databaseFactory;
private EfTrackerDbContext _dataContext;
public UnitOfWork(IDatabaseFactory<EfTrackerDbContext> databaseFactory)
{
_databaseFactory = databaseFactory;
}
public EfTrackerDbContext DataContext
{
get { return _dataContext ?? (_dataContext = _databaseFactory.Get()); }
}
public void Commit()
{
DataContext.Commit();
}
}
The EfTrackerDbContext is the actual EF context:
public class EfTrackerDbContext : DbContext, IUnitOfWork
{
public DbSet<Customer> Customers { get; set; }
public virtual void Commit()
{
base.SaveChanges();
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Customer>().ToTable("Customer");
}
}
And the DatabaseFactory is like:
public class DatabaseFactory<TContext> : DisposableObject, IDatabaseFactory<TContext> where TContext : DbContext, new()
{
private TContext _dataContext;
public TContext Get()
{
return _dataContext ?? (_dataContext = new TContext());
}
protected override void DisposeManagedResources()
{
if (_dataContext != null)
{
_dataContext.Dispose();
_dataContext = null;
}
}
}
The CustomerRepository:
public interface ICustomerRepository : IRepository<Customer>
{
IQueryable<Customer> Customers { get; }
}
public class CustomerRepository : RepositoryBase<EfTrackerDbContext, Customer>, ICustomerRepository
{
public CustomerRepository(IDatabaseFactory<EfTrackerDbContext> databaseFactory)
: base(databaseFactory)
{
}
public IQueryable<Customer> Customers
{
get { return DataContext.Customers; }
}
}
As you see, everything is injected. Registration looks like:
For<IDatabaseFactory<EfTrackerDbContext>>().HybridHttpOrThreadLocalScoped().Use<DatabaseFactory<EfTrackerDbContext>>();
For<IUnitOfWork>().HybridHttpOrThreadLocalScoped().Use<UnitOfWork>();
For<ICustomerRepository>().HybridHttpOrThreadLocalScoped().Use<CustomerRepository>();
Now, the question is about disposing the objects. The only place where IDisposable is implemented is DatabaseFactory, where _datacontext is disposed. I guess that is not enough, so I have following questions:
AddCustomerRequestHandler is injected, so it gets disposed if AddCustomer() service operation ends and garbage collection starts. Is this ok, or should I explicitely call Dispose on the AddCustomerRequestHandler at the end of the AddCustomer() operation and so have it implement IDisposable?
Should UnitOfWork also implement IDisposable, and do I have to call it explicitely?
How to dispose the EfTrackerDbContext ?
Other remarks?
In short, I'm looking for the right way to have everything disposed as soon as the service operation ends.
Thanks for the advice,
L
Whenever you use something that implements IDisposable you should Dispose it as soon as you don't need it any more.
If you use it as a field in a class, implement IDisposable in that class and iterate this process.
PS:
If you turn on Code Analysis like this:
you will get some warnings pointing you to this for free :D