Bounded context and Entity framework migrations - entity-framework

There's one thing I could't handle in implementing Bounded context with Entity Framework :
Having the entities (even their properties) distributed in multiple contexts , I feel the need to centralize the whole model in a specific area, that would be responsible for managing migrations.
Am I on the right track ?
Am I missing an important piece of the implementation puzzle?

You are right, I used multiple DbContext In my project too, I defined each mudule's DbContext In following format:
public class Module1Context : DbContext
{
public Moduled1Context()
: base("MyDatabase") //<=== I passed this ConnectionString parameter
// to all modules
{
}
...
}
public class Moduled2Context : DbContext
{
public Moduled2Context()
: base("MyDatabase")
{
}
...
}
And then defined a main DbContext that contains all DbSets from all module's DbContexts and use it for managing Migrations:
public class AllModulesContext : DbContext
{
public AllModulesContext()
: base("MyDatabase")
{
}
//dbSets from all modules
...
}

Related

DBContext Inherit from multiple base class

I have just implemented the DuendeIdentity Server and by DBContext looks like this.
public class DataContext : ApiAuthorizationDbContext<ApplicationUser>
{
public DataContext(
DbContextOptions options,
IOptions<OperationalStoreOptions> operationalStoreOptions) : base(options, operationalStoreOptions)
{
}
...
I now wish to implement some basic Database Auditing which I have successfully done in the past using this https://codewithmukesh.com/blog/audit-trail-implementation-in-aspnet-core/ however it is implemented in this way
public abstract class AuditableIdentityContext : IdentityDbContext
{
public AuditableIdentityContext(DbContextOptions options) : base(options)
{
}
With the DataContext then inheriting from it like
public partial class DataContext : AuditContext
{
public DataContext(DbContextOptions<DataContext> options)
: base(options)
{
}
I am trying to understand how I may use the two together. Any help would be appreciated.
C# doesn't have multiple inheritance.
Consider using your ApiAuthorizationDbContext separately from your application-specific DbContext. You can still use a DbSet<ApplicationUser> to reference your users from your application entities.

Entity Framework Repository Pattern - Database Catalogs

I have implemented Repository Pattern and Unit of Work into my ASP.NET Web API project.
It's working great. Now one question came to me about a Repository that can handle all about Setup Catalogs in my application.
Right now I have to create into my Unit of Work all public repositories that make a reference to an EF entity like below:
public IRepository<Document> Document { get { return GetStandardRepo<Document>(); } }
Where Document is an EF Entity. IRepository implements the following methods:
public interface IRepository<T> where T : class
{
IQueryable<T> GetAll();
IQueryable<T> GetAllReadOnly();
T GetById(int id);
void Add(T entity);
void Update(T entity);
void Delete(T entity);
void Delete(int id);
}
I have about 20 tables for Setup Catalogs in my database so If I follow this pattern I will have to create 20:
public IRepository<SetupEmployeeType> Document { get { return GetStandardRepo<SetupEmployeeType>(); } }
public IRepository<SetupMaritalStatus> Document { get { return GetStandardRepo<SetupMaritalStatus>(); } }
public IRepository<SetupRelationshipCode> Document { get { return GetStandardRepo<SetupRelationshipCode>(); } }
public IRepository<SetupLocationType> Document { get { return GetStandardRepo<SetupLocationType>(); } }
.....
.....
One solution I was thinking is to create my own custom IRepository implementation maybe ICatalogRepository like below:
public class CatalogRepository : EFRepository<EF Entity>, ICatalogRepository
{
public CatalogRepository (DbContext context) : base(context) { }
public IEnumerable<SetupEmployeeType> GetEmployeeTypes()
{
var catalog = DbContext
.Set<SetupEmployeeType>()
.ToList();
return catalog;
}
public IEnumerable<SetupMaritalStatus> GetMaritalStatus()
{
var catalog = DbContext
.Set<SetupMaritalStatus>()
.ToList();
return catalog;
}
}
My question is that CatalogRepository has to inherits from EFRepository but T is not just one entity because I will return diferent entities from diferent methods.
Is that the correct way to do this?
Yeah, don't use this anti pattern (generic repository wrapping DbContext while exposing EF entities). If you really want to use the Repository make the repository interface return ONLY business (or view models if it's a query repo) objects, never IQueryable or other details exposing EF or whatever are you using.
Simply put create a repository for your NEEDS, forget about generic stuff it's an anti pattern. So your CatalogRepository will use a DbContext to issue all the queries needed, then assemble a view model/business object from the results and returns that.
The app will know only about the Repo, never about EF. The queries will remain at the DAL level (not in your app/service/controller) and your app is decoupled, Separation of Concerns is respected.
A class wrapping DbContext is at best useless (what value does it bring?) and at worst a leaky abstraction. Make your life easier, if you want to work directly with EF entities and EF, work directly with EF. If you want to decouple the rest of the app from persistence details (note I've said persistence, not rdbms) use Repository properly. But don't kid yourself you're using the Repository pattern just because you have a class named repository. You should know exactly why are you using a pattern and what benefits it brings to your situation. It's not best practice if you don't understand why.

EF6 using multiples DbContext - (The entity type EntityName is not part of the model for the current context)

I have an application that we have some modules. We have for example FinancialModule and EmployeeModule.
I have an Core project that I created an abstract class called DefaultDbContext that inherits from DbContext and I have an abstract method called ModelCreating that all ConcreteClass (EFFinacialContext and EFEmployeeContext) should implement it to add mapping class.
My problem is that, I have an application with these modules and receiving this message "The entity type EntityName is not part of the model for the current context."
I have each module in running in another application and everything is okay, so,something is wrong when running together.
Who had the same problem using applications with multiples db context?
Thanks
Heres your problem
public class Context1 : DbContext
{
public IDbSet<Entity1> E1{get;set;}
}
public class Context2 : DbContext
{
public IDbSet<Entity2> E2{get;set;}
}
public class Entity1
{
//some stuff
}
public class Entity2
{
//some stuff
public Entity1 E1 {get;set;} //you arent allowed this as its not in your current dbcontext
}

Why DbContext doesn't implement IDbContext interface?

Why there is no IDbContext interface in the Entity Framework? Wouldn't it be easier to test things if there was an existing interface with methods like SaveChanges() etc. from which you could derive your custom database context interface?
public interface ICustomDbContext : IDbContext
{
// add entity set properties to existing set of methods in IDbContext
IDbSet<SomeEntity> SomeEntities { get; }
}
I see this IDbContext:
See this link And then you make a new partial class for your Entities Context With That interface.
public partial class YourModelEntities : DbContext, IDbContext
EDITED:
I edited this post, This Works for me.
My Context
namespace dao
{
public interface ContextI : IDisposable
{
DbSet<TEntity> Set<TEntity>() where TEntity : class;
DbSet Set(Type entityType);
int SaveChanges();
IEnumerable<DbEntityValidationResult> GetValidationErrors();
DbEntityEntry<TEntity> Entry<TEntity>(TEntity entity) where TEntity:class;
DbEntityEntry Entry(object entity);
string ConnectionString { get; set; }
bool AutoDetectChangedEnabled { get; set; }
void ExecuteSqlCommand(string p, params object[] o);
void ExecuteSqlCommand(string p);
}
}
YourModelEntities is your auto-generated partial class, and your need to create a new partial class with the same name, then add your new context interface, for this example is ContextI
NOTE: The interface hasn't implement all methods, because the methods are implemented in your auto-generate code.
namespace dao
{
public partial class YourModelEntities :DbContext, ContextI
{
public string ConnectionString
{
get
{
return this.Database.Connection.ConnectionString;
}
set
{
this.Database.Connection.ConnectionString = value;
}
}
bool AutoDetectChangedEnabled
{
get
{
return true;
}
set
{
throw new NotImplementedException();
}
}
public void ExecuteSqlCommand(string p,params object[] os)
{
this.Database.ExecuteSqlCommand(p, os);
}
public void ExecuteSqlCommand(string p)
{
this.Database.ExecuteSqlCommand(p);
}
bool ContextI.AutoDetectChangedEnabled
{
get
{
return this.Configuration.AutoDetectChangesEnabled;
}
set
{
this.Configuration.AutoDetectChangesEnabled = value;
}
}
}
}
I was thinking also about that, I assume you are going to use it for mocking DbContext. I find no reason for that, except that you will need to implement your own DbSet manually in your anyway for your mocked class (so will need to rewrite your own interface anyway).
Just create a mock DbContext extending your production DbContext overriding the methods that complicate testing. That way, any changes to the production DbContext are automatically reflected in the tests, save for the overridden methods. For any other classes that deal with persistence and take the DbContext just extend them as well passing in the extended mock DbContext.
namespace Test.Mocks
{
public sealed class MockDatabaseContext : MainProject.Persistence.Database.DatabaseContext
{
public MockDatabaseContext(ConfigurationWrapper config) : base(config)
{
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
var dbPath = "test.db";
optionsBuilder.UseSqlite($"Filename={dbPath}");
}
}
}
namespace Test.Mocks
{
public class MockInventoryFacade : InventoryFacade
{
public MockInventoryFacade(MockDatabaseContext databaseContext) : base(databaseContext)
{
}
}
}
There is no IDbContext because it would be useless, the only implementation of it would be the DbContext.
EF team is also going this way with IDbSet if you look at this design meeting note
For me, the real problem with EF when it comes to unit testing is the DbConnection in the DbContext, fortunately there is Effort a nice project on codeplex that starts to fill this.
Effort is a powerful tool that enables a convenient way to create automated tests for Entity Framework based applications.
It is basically an ADO.NET provider that executes all the data operations on a lightweight in-process main memory database instead of a traditional external database. It provides some intuitive helper methods too that make really easy to use this provider with existing ObjectContext or DbContext classes. A simple addition to existing code might be enough to create data driven tests that can run without the presence of the external database.
With this, you can leave your DbContext and DbSet as is and do your unit tests easily.
The only drawback with this is the difference between Linq providers where some unit tests may pass with effort and not with the real backend.
UPDATE with EF7
I still maintain that IDbContext would be useless and the problem comes from the DbConnection.
EF7 will not have an IDbContext either, in order to do unit testing they are now giving an in memory provider.
You can see Rowan Miller doing a demo here: Modern Data Applications with Entity Framework 7

Update method for generic Entity framework repository

I have a repository like that:
public class Repository<T> : IRepository<T> where T : class
{
private readonly IRepositoryContext _repositoryContext;
public Repository(IRepositoryContext repositoryContext)
{
_repositoryContext = repositoryContext;
_objectSet = repositoryContext.GetObjectSet<T>();
}
public virtual void Update(T entity)
{
ObjectSet.AddObject(entity);
_repositoryContext.ObjectContext.ObjectStateManager.ChangeObjectState(entity, EntityState.Modified);
_repositoryContext.SaveChanges();
}
}
Now that actually works for all scalar properties of the entity, but all the other entities that associated with properties of entity typeOf(T), don't care that entity state is modified, and EF simply adds new data.
So, if you do for example Repository<Student>.Update(), and you only changed the name, it will find the right Student and change his name, but it also will change the Campus, although you already have a Campus associated with that student, it will be created again with a different CampusId.
Show me please the correct way to do updates in this situation.
What I did when I wanted to follow generic approach was translated to your code something like:
public class Repository<T> : IRepository<T> where T : class
{
...
public virtual void Update(T entity)
{
if (context.ObjectStateManager.GetObjectStateEntry(entity).State == EntityState.Detached)
{
throw new InvalidOperationException(...);
}
_repositoryContext.SaveChanges();
}
}
All my code then worked like:
var attachedEntity = repository.Find(someId);
// Merge all changes into attached entity here
repository.Update(attachedEntity);
=> Doing this in generic way moves a lot of logic into your upper layer. There is no better way how to save big detached object graphs (especially when many-to-many relations are involved and deleting of relations is involved).