CastleWindsor, Generic Repository and two database contexts - c#

I have two separate databases for storing documents and users. Also I've implemented generic repository pattern:
public class Repository<T> : IRepository<T> where T : class
{
public DbContext Context { get; set; }
public Repository()
{
}
public IEnumerable<T> Get(Expression<Func<T, bool>> expression)
{
return Context.Set<T>().Where(expression).AsEnumerable();
}
public void Add(T entity)
{
Context.Set<T>().Add(entity);
}
public void Delete(T entity)
{
Context.Set<T>().Remove(entity);
}
public void Update(T entity)
{
Context.Set<T>().Attach(entity);
Context.Entry<T>(entity).State = EntityState.Modified;
}
public void SaveChanges()
{
Context.SaveChanges();
}
}
The problem is that entities are stored in different DbContexts and I can't use something like this:
container.Register(Component.For(typeof(IRepository<>)).ImplementedBy(typeof(Repository<>));
How can I specify which DbContext should be used for each entity?
For example, if I want create Repository that means that one database should be used, but if I want Repository another context should be used.
Or I should create two repo classes, like this:
public class AttachmetRepository<T> : IRepository<T> where T : class
{
public AttachmetsDbContext Context { get; set; }
...
}
public class UserRepository<T> : IRepository<T> where T : class
{
public UsersDbContext Context { get; set; }
...
}
The reason why I don't want to use two different repositories is to keep services simple, something like this:
public class SomeService: ISomeService
{
public IRepository<User> UserRepository { get; set; } //database 1
public IRepository<Comment> CommentsRepository { get; set; } //database 1
public IRepository<Attachment> AttachmentRepository { get; set; } //database 2
...
}
UPD:
As Ognyan suggested I've used FactoryMethod and this helped! Thanks a lot, Ognyan!
I'm new to CastleWindsor and I'm not sure its the best and fastest way, but here is my code:
public class EFDatabaseInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Component.For<AttContext>().LifeStyle.PerWebRequest);
container.Register(Component.For<DefContext>().LifeStyle.PerWebRequest);
container.Register(Component.For(typeof(IRepository<>)).UsingFactoryMethod((kernel, context) =>
{
var genericType = context.RequestedType.GetGenericArguments()[0];
Type type = typeof(Repository<>).MakeGenericType(genericType);
object repository = Activator.CreateInstance(type);
PropertyInfo dbContextProperty = type.GetProperty("Context");
if (genericType == typeof(Attachment))
{
dbContextProperty.SetValue(repository, kernel.Resolve<AttContext>());
}
else
{
dbContextProperty.SetValue(repository, kernel.Resolve<DefContext>());
}
return repository;
}).LifeStyle.PerWebRequest);
}
}

First you need not to hard code the DbContext inside the repository. You can remake your repository like this :
public class Repository<T> : IRepository<T> where T : class
{
private readonly DbContext _dbContext;
// you can even make it IDbContextProvider with .Current() method in order not
// to place a hard dependency but depend on Interface which is the proper way.
// I was in a hurry and did not want to overcomplicate the implementation.
public Repository(DbContext dbContext)
{
_dbContext = dbContext;
}
protected IDbSet<T> CreateSet<T>() where T : class
{
return _dbContext.Set<T>();
}
public virtual T Find(int id)
{
return CreateSet<T>().Find(id);
}
...
}
After that you need a factory method and a way to distinguish the destination db. One way to distinguish is to get the info from the CreationContext of the factory method :
private static DbContext DbContextFactoryMethod(IKernel k, ComponentModel cm, CreationContext c)
Here you can traverse the resolution stack and see if this is part of graph that contains IRepository or other entity and choose your database.
This way you will get the proper DbContext inside your repository without sticking all of them inside which will become more and more cumbersome with time.

Related

What design pattern should I use in DAL while having multiple database sources with different models?

I've an already existing SQL database that has table Car for example that looks like this
public class Car
{
public string Brand { get; set; }
public string AvailableColorsCommaSperated { get; set; }
}
Now I'm working on migrating to MongoDb so that the data could look like that
public class Car
{
public string Brand { get; set; }
public List<string> Colors { get; set; }
}
But I've to maintain the SQL database at the same time as it will remain used for sometime even after migration.
Now in my DAL layer I had a Master interface and class that looks like Repository pattern which the interface was like that
public interface ICarDAL
{
List<Car> GetAllCars();
}
public class CarDAL : ICarDAL
{
private readonly ICarSQL carSQL;
public CarDAL(ICarSQL carSQL)
{
this.carSQL = carSQL;
}
public List<Car> GetAllCars()
{
return carSQL.GetAllCars();
}
}
While to implement that using the SQLContext another interface and class with implementation exists as so
public interface ICarSQL : ICarDAL
{
new List<Car> GetAllCars();
}
public class CarSQL : ICarSQL
{
private readonly DbContext dbContext;
public CarSQL(DbContext dbContext)
{
this.dbContext = dbContext;
}
public List<Car> GetAllCars()
{
// Get Cars..
}
}
I could have no problem of adding a seperate layer for the Mongo to inherit from the ICarDAL and implement the functions on its own, but the problem is that I will have different Car Model for each one of them (the Car is just an example)
How can I abstract the DAL layer so that I can make the CRUD operations with different Models to different Databases? and am I going to need different context or use the same one with a factory to distinguish between different databases classes?
you can make your interface more generic
public interface IGenericRepository<T> where T : class
{
IEnumerable<T> GetAll();
T GetById(object id);
void Insert(T obj);
void Update(T obj);
void Delete(object id);
void Save();
}
so each dal layer will implement it's own version
you can even use a different type for an ID
for example:
public interface IGenericRepository<T,K> where T : class
{
IEnumerable<T> GetAll();
T GetById(K id);
void Insert(T obj);
void Update(T obj);
void Delete(K id);
void Save();
}

Can't add generic Interface to List with same constraint

I'm struggling with generics and don't really know what I'm doing wrong.
This is my example:
public class Repository // Base-class for all repositories
{
public virtual int GetStatus()
{
return 0;
}
}
Repository is just a base class.
public class CarRepository : Repository // base-class for all car repositories
{
private object dataSource;
public override int GetStatus()
{
return dataSource.GetHashCode(); // dummy
}
public virtual int GetPrice(string carName)
{
if (carName.Equals("BMW", StringComparison.OrdinalIgnoreCase)) {
return 100;
}
return 50;
}
}
CarRepository simply provides basic methods to interact with cars.
public class HttpCarRepository : CarRepository // loads the car data from REST Api
{
private dynamic httpClient; // just as an example
public override int GetStatus()
{
return httpClient.IsConnected();
}
public override int GetPrice(string carName)
{
return httpClient.GetAsync("/rest/car/BMW").Result;
}
}
There might also be an DataBaseCarRepository that loads the data from a database. You get the point.
That's for the setup.
Now, I want to cache the results. To keep it generic, I've created this construct:
public interface ICache<TRepo> // Basic Cache Interface
where TRepo : Repository
{
TRepo Repository { get; set; }
}
public class CarCache : CarRepository, ICache<CarRepository>
{
public CarRepository Repository { get; set; }
private dynamic cache;
public CarCache(CarRepository repo)
{
this.Repository = repo;
}
public override int GetPrice(string carName)
{
if (!this.cache.Contains(carName)) {
this.cache.Add(carName, this.Repository.GetPrice(carName));
}
return cache[carName];
}
}
CarCache derives from the base class CarRepository to make it possible to override the methods. It also implements ICache<T> which provides a reference to an actual
implementation of CarRepository, such as HttpCarRepository.
Now I want to add the CarCache to a list of caches.
public class Manager
{
public List<ICache<Repository>> Caches;
}
I've used Repository as the generic type because the ICache<T> interface constraints the type to Repository.
Now the problem:
I've got a method to add a cache that looks like this
static void Add<TCache>(Repository repo)
where TCache : Repository, ICache<TCache>
{
ICache<TCache> newEntry = Activator.CreateInstance(typeof(TCache), repo) as ICache<TCache>;
Caches.Add(newEntry); // Error: Cannot convert from ICache<TCache> to ICache<Repository>
}
That confuses me. From my understanding this should work because I've added the constraint where TCache : Repository to the method, so adding an item of that type
to a list of ICache<Repository> should work. It's the same constraint.
What's the problem here?
One solution would be to make ICache<TRepo> covariant.
You would need to make TRepo Repository get-only to comply with covariant restrictions:
public interface ICache<out TRepo> where TRepo : Repository
{
TRepo Repository { get; }
}
This would work fine as long as the property is only set via your constructor:
public class CarCache : CarRepository, ICache<CarRepository>
{
public CarRepository Repository { get; }
public CarCache(CarRepository repo)
{
this.Repository = repo; // Fine to set Repository here
}
// ...
}
Or you could make the setter private to allow other methods of the implementation class to set the value:
public class CarCache : CarRepository, ICache<CarRepository>
{
public CarRepository Repository { get; private set; }
// ...
void SetRepository(CarRepository repo)
{
this.Repository = repo;
}
}

EF Core, DI, Repository pattern and issue with base repository structure

I have .net core rest api, which contains hybrid structure in which it only contains repositories and not the service layer.
Now, there is one issue that I am facing with base repository and main structure. let me explain the issue first.
So, consider one entity. let's say Product and below is the definition for that entity. this entity has one base class called FullAuditedEntity.
[Table(name: "Products")]
public class Product : FullAuditedEntity
{
public string Name { get; set; }
}
public class FullAuditedEntity: IFullAuditedEntity
{
public FullAuditedEntity() { }
[Key]
public virtual int Id { get; set; }
}
public interface IFullAuditedEntity
{
int Id { get; set; }
}
The Base repository and it's interfaces are as below.
public class EntityBaseRepository<T> : IEntityBaseRepository<T> where T : class, IFullAuditedEntity, new()
{
private readonly ApplicationContext context;
public EntityBaseRepository(ApplicationContext context)
{
this.context = context;
}
public virtual IEnumerable<T> items => context.Set<T>().AsEnumerable().OrderByDescending(m => m.Id);
public virtual T GetSingle(int id) => context.Set<T>().FirstOrDefault(x => x.Id == id);
}
public interface IEntityBaseRepository<T> where T : class, new()
{
IEnumerable<T> items { get; }
T GetSingle(int id);
}
So, my Product repository will be like this.
public interface IProductRepository : IEntityBaseRepository<Product> { }
public class ProductRepository : EntityBaseRepository<Product>, IProductRepository
{
private readonly ApplicationContext context;
public ProductRepository(ApplicationContext context) : base(context: context)
{
this.context = context;
}
}
Now, up-to here everything is good, I can access this repository in controllers and can perform the actions that are listed in base class.
Issue I am facing : So with this structure, If I tries to add any new entity without FullAuditedEntity (see Product entity above, I have base class full audited entity over there), my structure of repository fails and it gives error.
let's say if I tries to add new entity Implementation, and this new entity has a random Id, so I do not want to inherit the FullAuditedEnitity base class. now in this case most of the thing will work fine but when I will try to create repository for Implementation entity, it will give generic error. see below snap of that.
What I tried so far...
I was thinking to create a parallel Base repository which does not inherit FullAuditedEntity as a generic class but I am not sure if it's best practice or not. also my concern is that what if I am doing any mistake in my current structure of repository pattern and Dependency injection?
Any help world be best and really appreciated.
Thank you in advance for your time.
Repositories are usually mapped to database tables. Database table should always have some column which can uniquely identify the row in table and it is common practice to call this column as Id. So you correctly implemented your FullAuditedEntity as there is Id property. However, your Id has always type of int. I suggest you to use the following construction and then your Id would be any type of struct such as int, decimal, Guid, and etc:
/// <summary>
/// Abstraction of the Entity
/// </summary>
public interface IEntity
{
object Id { get; set; }
}
/// <summary>
/// Base class for IDs
/// </summary>
public abstract class Entity<T>: IEntity where T: struct
{
public T Id { get; set; }
object IEntity.Id
{
get { return Id; }
set {
Id = (T)value;
}
}
}
public class EntityBaseRepository<T> : IEntityBaseRepository<T> where T : class, IEntity, new()
{
// The code is omitted for the brevity
}
In addition, try to avoid entities without Id like Implementation as in future you will have to figure out how to find rows without Id in your database table.
UPDATE:
If you do not want to inherit FullAuditedEntity, then you can create BaseRepository<T> and then derive it in the EntityBaseRepository.
public abstract class BaseRepository<T> : IEntityBaseRepository<T> where T : class, new()
{
public virtual IEnumerable<T> items => throw new NotImplementedException();
public virtual T GetSingle(int id)
{
throw new NotImplementedException();
}
}
public class EntityBaseRepository<T> : BaseRepository<T> where T : class
, IFullAuditedEntity, new()
{
public override IEnumerable<T> items => base.items;
public override T GetSingle(int id)
{
return base.GetSingle(id);
}
}
and then your Implementation repository:
public interface IImplementationRepository : IEntityBaseRepository<Implementation> { }
public class ImplementationRepository: BaseRepository<Implementation>
, IImplementationRepository
{
public override Implementation GetSingle(int id)
{
return base.GetSingle(id);
}
}
UPDATE 1:
In my view, it is better to use services(Service layer) which consume ITRepository<T>.
Because it gives to you new abilities such as:
Add some calculations on data which got by Repository
Remap your entities which are pulled by the Repository
It is one additional layer of decoupling. So when you edit your service layer, then you don't need to edit Repository layer and then recompile your assembly

Using multiple DbContexts with a generic repository and unit of work

My application is getting larger and so far I have a single MyDbContext which has all the tables I need in my application. I wish (for the sake of overview) to split them up into multiple DbContext, like MainDbContext, EstateModuleDbContext, AnotherModuleDbContext and UserDbContext.
I am unsure how this is done probably as I am right now using dependecy injection (ninject) to place my DbContext on my UnitOfWork class like:
kernel.Bind(typeof(IUnitOfWork)).To(typeof(UnitOfWork<MyDbContext>));
Should I drop this approach with dependency injection and explicit set the DbContext I wish to use on my services like:
private readonly EstateService _estateService;
public HomeController()
{
IUnitOfWork uow = new UnitOfWork<MyDbContext>();
_estateService = new EstateService(uow);
}
Instead of:
private readonly EstateService _estateService;
public HomeController(IUnitOfWork uow)
{
_estateService = new EstateService(uow);
}
Or this there another better approach? Also as a side question, I dont like passing the uow to my service - is there another (better) approach?
Code
I have this IDbContext and MyDbContext:
public interface IDbContext
{
DbSet<T> Set<T>() where T : class;
DbEntityEntry<T> Entry<T>(T entity) where T : class;
int SaveChanges();
void Dispose();
}
public class MyDbContext : DbContext, IDbContext
{
public DbSet<Table1> Table1 { get; set; }
public DbSet<Table2> Table1 { get; set; }
public DbSet<Table3> Table1 { get; set; }
public DbSet<Table4> Table1 { get; set; }
public DbSet<Table5> Table1 { get; set; }
/* and so on */
static MyDbContext()
{
Database.SetInitializer<MyDbContext>(new CreateDatabaseIfNotExists<MyDbContext>());
}
public MyDbContext()
: base("MyDbContext")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
}
}
Then I have this IRepository and the implementation:
public interface IRepository<T> where T : class
{
IQueryable<T> GetAll();
void Add(T entity);
void Delete(T entity);
void DeleteAll(IEnumerable<T> entity);
void Update(T entity);
bool Any();
}
public class Repository<T> : IRepository<T> where T : class
{
private readonly IDbContext _context;
private readonly IDbSet<T> _dbset;
public Repository(IDbContext context)
{
_context = context;
_dbset = context.Set<T>();
}
public virtual IQueryable<T> GetAll()
{
return _dbset;
}
public virtual void Add(T entity)
{
_dbset.Add(entity);
}
public virtual void Delete(T entity)
{
var entry = _context.Entry(entity);
entry.State = EntityState.Deleted;
_dbset.Remove(entity);
}
public virtual void DeleteAll(IEnumerable<T> entity)
{
foreach (var ent in entity)
{
var entry = _context.Entry(ent);
entry.State = EntityState.Deleted;
_dbset.Remove(ent);
}
}
public virtual void Update(T entity)
{
var entry = _context.Entry(entity);
_dbset.Attach(entity);
entry.State = EntityState.Modified;
}
public virtual bool Any()
{
return _dbset.Any();
}
}
And the IUnitOfWork and implemention which handles the work done with the DbContext
public interface IUnitOfWork : IDisposable
{
IRepository<TEntity> GetRepository<TEntity>() where TEntity : class;
void Save();
}
public class UnitOfWork<TContext> : IUnitOfWork where TContext : IDbContext, new()
{
private readonly IDbContext _ctx;
private readonly Dictionary<Type, object> _repositories;
private bool _disposed;
public UnitOfWork()
{
_ctx = new TContext();
_repositories = new Dictionary<Type, object>();
_disposed = false;
}
public IRepository<TEntity> GetRepository<TEntity>() where TEntity : class
{
// Checks if the Dictionary Key contains the Model class
if (_repositories.Keys.Contains(typeof(TEntity)))
{
// Return the repository for that Model class
return _repositories[typeof(TEntity)] as IRepository<TEntity>;
}
// If the repository for that Model class doesn't exist, create it
var repository = new Repository<TEntity>(_ctx);
// Add it to the dictionary
_repositories.Add(typeof(TEntity), repository);
return repository;
}
public void Save()
{
_ctx.SaveChanges();
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (this._disposed) return;
if (disposing)
{
_ctx.Dispose();
}
this._disposed = true;
}
}
Don't split your modular data pieces into multiple DbContexts unless there are logical seams for doing so. Entities from DbContextA cannot have automatic navigation or collection properties with entities in DbContextB. If you split the context, your code would have to be responsible for manually enforcing constraints and loading related data between contexts.
For "sake of overview" (a.k.a. keeping your sanity), you can still organize your CLR code and database tables by module. For the POCO's, keep them in different folders under different namespaces. For tables, you can group by schema. (However you probably should also take security considerations into account when organizing by SQL schema. For example, if there are any db users that should have restricted access to certain tables, design the schemas according to those rules.) Then, you can do this when building the model:
ToTable("TableName", "SchemaName"); // put table under SchemaName, not dbo
Only go with a separate DbContext when its entities have no relationships with any entities in your first DbContext.
I also agree with Wiktor in that I don't like your interface & implementation design. I especially don't like public interface IRepository<T>. Also, why declare multiple public DbSet<TableN> TableN { get; set; } in your MyDbContext? Do me a favor, read this article, then read this one.
You can greatly simplify your code with an EF interface design like this:
interface IUnitOfWork
{
int SaveChanges();
}
interface IQueryEntities
{
IQueryable<T> Query<T>(); // implementation returns Set<T>().AsNoTracking()
IQueryable<T> EagerLoad<T>(IQueryable<T> queryable, Expression<Func<T, object>> expression); // implementation returns queryable.Include(expression)
}
interface ICommandEntities : IQueryEntities, IUnitOfWork
{
T Find<T>(params object[] keyValues);
IQueryable<T> FindMany<T>(); // implementation returns Set<T>() without .AsNoTracking()
void Create<T>(T entity); // implementation changes Entry(entity).State
void Update<T>(T entity); // implementation changes Entry(entity).State
void Delete<T>(T entity); // implementation changes Entry(entity).State
void Reload<T>(T entity); // implementation invokes Entry(entity).Reload
}
If you declare MyDbContext : ICommandEntities, you just have to set up a few methods to implement the interface (usually one-liners). You can then inject any of the 3 interfaces into your service implementations: usually ICommandEntities for operations that have side effects, and IQueryEntities for operations that don't. Any services (or service decorators) responsible only for saving state can take a dependency on IUnitOfWork. I disagree that Controllers should take a dependency on IUnitOfWork though. Using the above design, your services should save changes before returning to the Controller.
If having multiple separate DbContext classes in your app ever makes sense, you can do as Wiktor suggests and make the above interfaces generic. You can then dependency inject into services like so:
public SomeServiceClass(IQueryEntities<UserEntities> users,
ICommandEntities<EstateModuleEntities> estateModule) { ... }
public SomeControllerClass(SomeServiceClass service) { ... }
// Ninject will automatically constructor inject service instance into controller
// you don't need to pass arguments to the service constructor from controller
Creating wide per-aggregate (or even worse per-entity) repository interfaces can fight with EF, multiply boring plumbing code, and over-inject your constructors. Instead, give your services more flexibility. Methods like .Any() don't belong on the interface, you can just call extensions on the IQueryable<T> returned by Query<T> or FindMany<T> from within your service methods.
Your unit of work interface is not generic but the implementation is. The easiest way to clean up this would be to decide and follow the same convention.
For example, make your interface generic also. This way you could register three different interfaces (the same interface with three different generic parameters) to three different implementations:
container.Bind( typeof<IUnitOfWork<ContextOne>> ).To( typeof<UnitOfWork<ContextOne>> );
...
And yes, this is a good idea to inject your unit of works into controllers / services.

In a knot with Generics

I have the following domain object:
public class DomainObject<T,TRepo>
where T : DomainObject<T>
where TRepo : IRepository<T>
{
public static TRepo Repository { get;private set; }
}
A repository interface:
public interface IRepository<T> //where T : DomainObject<T> // The catch 22
{
void Save(T domainObject);
}
An implementation of the 2:
public class User : DomainObject<User,MyRepository>
{
public string Name { get;private set;}
}
public class MyRepository : IRepository<User>
{
public List<User> UsersWithNameBob()
{
}
}
So adding another method that isn't inside IRepository.
I want to enforce the repository as an IRepository while above it could be any type.
A small sidenote: I'm writing this for small systems with very few domain objects. I'm not looking to create anything that uses IoC, but rather something that is easy and simple to consume.
Thanks
Your implementation of DomainObject is only specifying one generic type argument instead of two. Why isn't it:
public class User : DomainObject<User, MyRepository>
{
public string Name { get;private set;}
}
If that doesn't work, could you explain in what way it doesn't do what you need?
Not exactly sure what you want, but something like this compiles:
public class DomainObject<T, TRepo>
where T: DomainObject<T, TRepo>
where TRepo: IRepository<T, TRepo>
{
public static TRepo Repository
{
get;
private set;
}
}
public interface IRepository<T, TRepo>
where T: DomainObject<T, TRepo>
where TRepo: IRepository<T, TRepo>
{
void Save(T domainObject);
}

Categories