WebAPI - Repository class with DbContext object creation - entity-framework

I am new to the ASP.NET WebAPI project and building the new project with the following structure :-
Project.MainAPIService
Project.BusinessManager
Project.Model
Project.Repository
Project.Common
I am using Autofac to perform the DI in the whole project. And the flow is like this :-
API controller >>>>>> (DI) Business Manager >>>> (DI) Repository & creates the DBContext object manually.
My Repository class is looking like this. And now i want to pass the client-name dynamically into the Repository class, so that it makes the DB connection to the particular client db only. But i unable to pass the client-name from businessManager project to PDLRepository and further down to DBContext class.
public class MyRepository : IMyRepository, IDisposable
{
myContext _context = new myContext("ClientX");
private IGenericRepository<Mapping> _docMappingGenericRepo;
private IGenericRepository<Document> _DocGenericRepo;
private IGenericRepository<Activity> _activityGenericRepo;
}
mycontext class looks like this :-
public partial class mycontext : DbContext
{
public mycontext (string ClientName)
: base(ConnectionUtil.GetConnectionString(ClientName))
{ }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
Database.SetInitializer<myContext>(null);
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
public virtual DbSet<DocumentMapping> DocumentMapping { get; set; }
public virtual DbSet<Document> Document { get; set; }
}
Please suggest your views how to fix the myContext or MyRepository class accordingly. How will i pass the client-name from BusinessManager to Repository to DBContext class ?
Please help me out here.

Do not create myContext in Repository. Remove following line from Repository.
myContext _context = new myContext("ClientX");
Instead, create and manage myContext in BusinessManager. As BusinessManager already know ClientName, it can be created there without trouble with the same line we removed from Repository.
Now, inject myContext in Repository.
You apparently have multiple databases; one per client. So one database represent one client. Connection represents Database and myContext is handling Connection. So, approach I mentioned above makes more sense.
Repository executes the action, it should not control Connection. Using this approach, you can also include multiple Repositories in one myContext which will help you cover all those repositories under one transaction/UoW.
This answer explains how to do this with Dapper. Technology may not be related to you; but rest of the details may help you.

Related

DbSetT<T> vs IDbSet<T>

Recently, I've got request to make my DbContext model mockable.
However, currently it is defined like this:
public MyDbContext : DbContext
{
public DbSet<Employee> Employees {get;set;}
}
I was thinking to abstract it to:
public interface IMyDbContext
{
IDbSet<Employee> Employees {get;set;}
}
public MyDbContext : DbContext, IMyDbContext
{
IDbSet<Employee> Employees {get;set;}
}
Do I lose anything if I swap DbSet with IDbSet in my MyDbContext implementation?
I think the mock and real database object should share the same interface. That way you can swap out your database implementation without affecting clients. Mocking is easier, too. Aspect oriented programming is easier. I can't think of a good reason not to start both with an interface.

Code First Migrations with two DataContext

In my app i have two DataContexts, ApplicationDbContext created by default ,which inherits from IdentityDbContext and DomainContext for my model. Now i am getting some issues when updating the database using Migrations, when i execute
Add-Migration to DomainContext in the migration file created is included the code to Drop all the tables related to ApplicationDbContext. I have googled and i have not found any satisfactory answer yet, the only rasonable solution suggest to mingle both DBContexts but that sound weird to me because ApplicationDbContext inherit from IdentityDbContext.
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base( "DBContextConnString" )
{
}
}
public class DomainContext:DbContext {
public DomainContext() : base( "DBContextConnString" ) { }
public DbSet<State> States { get; set; }
protected override void OnModelCreating( DbModelBuilder modelBuilder ) {
modelBuilder.HasDefaultSchema( "Workflow" );
base.OnModelCreating( modelBuilder );
}
}
One of the The new fetures exposed by EF6 state "Multiple Contexts per Database removes the previous limitation of one Code First model per database when using Migrations or when Code First automatically created the database for you." (Read it here). But in practice is a pain to implement this or maybe i am missing something very very obvious.
My question in short, what is the way to go to keep this two different DBContexts living in armony?
After some experimentation i conclude that the more pragmatic way is to mingle both DbContext into one, so i decide to move my domain entities to IdentityDbContext.

Multiple DbContext classes use the same connection string?

For example, I have following DbContext classes.
public class AppDbContext : DbContext {
...
}
public class LogDbContext : DbContext {
...
}
public class FooDbContext : DbContext {
...
}
If a connection string named AppDbContext is on the App.Config and I want other DbContext classes to share the same connection string as AppDbContext, could I just pass the string "AppDbContext" as the parameter for the ctor of LogDbContext and FooDbContext. For example,
public class FooDbContext : DbContext {
public FooDbContext : base("AppDbContext") { }
}
Does it have any side effects ?
Update 2013/1/9
After trying #ShinH2S's suggestion and somethings, I give up this way, and decide give different Dbcontext derived classes with different connectionStrings and database. I have try a test project and put it on GitHub. It will throw a runtime exception when the entityframework detects the database scheme is changed because the AppDbContext and FooDbContext have different schemas. If I assign a DropCreateDatabaseIfModelChanges strategy to both DbContext derived classes, one of them will be dropped because the models is different to another.
Update 2017/10
This is an old problem. In my memory, EF6 and above versions can have different migration history for multiple context in the same migration table.
I prefer this answer at SO. I had not been coding with C# about 2 years.
IMHO, there is no side effects. But if it was me I will just create a base class that inherits from DbContext class BaseDbContextthen all the contexts (AppDbContext, LogDbContext and FooDbContext ) will derive from BaseDbContext.

IUnitOfWork how to use - best practice

I'm using EF4.3.1 in a .Net4.0 web forms (not MVC!) application.
I tend to use the repository pattern with an IUnitOfWork interface. But I'm wondering if I'm following best practices, especially since most examples I've followed are based on MVC apps.
I will say it's only a small web app, so that may affect the solution choices.
The solution currently has 3 projects, Model, Logic and Site. Model contains the codefirst entities and the IUnitOfWork interface. Logic contains the repositories and service layer. Site obviously contains the website, codebehind, etc.
I don't use any third-party inject utility (ninject, etc). I manually inject repositories with an IUnitOfWork i.e.
public BookingRepository(IUnitOfWork unitOfWork)
I'm less clear what to do with the service layers, should the IUnitOfWork also exisit in the Site project, or only exist in the Logic and Model layers.
Currently I inject a repository and a unit of work into a service i.e.
public BookingService(IUnitOfWork unitOfWork, IBookingRepository repository, IAppSettings appSettings)
But this means the commiting (save to db) is done at the Site level, but I wonder if it should be done in the service layer. It also means, that since my IUnitOfWork is declared in my model layer, I need a reference to Model in my site also.
What can I do better? Am I doing anything right? lol
Dmitry is right. Here is a sample implementation of a Unit of work. The benefit here is that the unit of work pattern coordinates the work of the multiple repositories by enforcing a single database context class shared by all of them.
This is a good resource for beginning to understand how these patterns can be used together. It is valid for both MVC and web Forms development. Implementing the Repository and Unit of Work Patterns in an ASP.NET MVC Application
public class UnitOfWork : IDisposable
{
private DbContext _context;
private PersonRepository _personRepository;
private CompanyRepository _companyRepository;
public UnitOfWork(DbContext context)
{
this._context = context;
}
public void Commit()
{
_context.SaveChanges();
}
// We lazy-load our repositories...
public PersonRepository PersonRepository
{
get
{
if (this._personRepository == null)
{
this._personRepository = new PersonRepository(context);
}
return _personRepository;
}
}
public CompanyRepository
{
get
{
if (this._companyRepository == null)
{
this._companyRepository = new CompanyRepository(context);
}
return _companyRepository;
}
}
//IDisposable implementation removed for brevity...
}

EF how to restrict users to not access the DbContext and add children of aggregate roots?

I use the repository pattern and UnitOfWork. This is kept in a separate project together with my domain model. I realize it might be tempting for users to go to the DbContext directly and add i.e. a child of a aggregate root.
Should I mark everything internal except for repositories and UnitOfWork? The reason for asking is that I've not seen this done in any of the documentation, examples or even the subject addressed in what I've read so far.
Do not expose the DbContext to your domain layer and UI layer. Your repository pattern implementation is a leaky abstraction.
Domain Layer
public interface IUnitOfWork : IDisposable
{
int SaveChanges();
}
public interface IRepository<TEntity>
{
}
Data Access layer
internal class UnitOfWork : DbContext, UnitOfWork
{
}
internal class Repository<TEntity> : IRepository<TEntity>
{
}