Multiple DBContext, Include some models in other database context model - entity-framework

In our projects, we use UnitOfWork Design Pattern.
In UnitOfWork, our DatabaseContext is hide from outside the project.
In Server Project (WebAPI), we want use Identity for User Authentication and Authorization. in this case, cant access DabaseContext, because its hide behind the UnitOfWork.
We Add new Database Context for Identity. and its public to access it from server project.
Now there is problem with join some models in different database context:
Identity tables exist in IdentityDatabaseContext with custom Scheme: "identity"
Application tables exist in DatabaseContext with general scheme: "dbo"
There is a Model (like News) in Application that have a property of identity.User
UnitOfWork
DatabseContext
News
NewsId
Title
...
CreateUser -> CreateUser is a User from Identity (from IdentityDatabaseContext)
Code:
NewRepository.GetAll().Include(x=>x.CreateUser)
If we use Include "User" in News, we got error:
The expression 'p.User' is invalid inside an 'Include' operation,
since it does not represent a property access: 't => t.MyProperty'. To
target navigations declared on derived types, use casting ('t =>
((Derived)t).MyProperty') or the 'as' operator ('t => (t as
Derived).MyProperty'). Collection navigation access can be filtered by
composing Where, OrderBy(Descending), ThenBy(Descending), Skip or Take
operations. For more information on including related data, see
http://go.microsoft.com/fwlink/?LinkID=746393.

I think you're decomposing your app at the repository level, which is not the right level to compartmentalize your domain.
It's better to modularize your app into Bounded Context(in terms of DDD) if need be, if not stick to a single instance of DbContext at least for a Bounded Context.

Related

Multiple UserManagers

I'm trying to have two different UserManagers.
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create);
app.CreatePerOwinContext<CustomUserManager>(CustomUserManager.Create);
app.CreatePerOwinContext<CustomRoleManager>(CustomRoleManager.Create);
Both ApplicationUser and CustomUser inherit IdentityUser.
How do I configure OnModelCreating to support the Roles/Claims/Logins correctly?
Am I doing something that would be considered bad practice? I just want to completely separate these two types of users. I don't want TPH since I need different required properties.
UPDATE
To further explain why I think I need this, is because I would like to have different roles and properties for these two types of users. If they share the same table, I would need a optional one-to-one relation to add properties, allow same UserNames, and who knows what else.
I made two custom UserManagers (e.g., CustomUserManager : UserManager<CustomUser>) where CustomUser inherits from IdentityUser and is specified as Table per Type with [Table("CustomUser")] on the class.
The context needs to be IdentityDbContext, or DbContext with the same DbModelBuilder settings.
Same thing goes for the roles if needed (e.g., CustomRoleManager : RoleManager<CustomRole>), they will be Table per Hierarchy. Though there isn't much use to this unless you modify the Authorize attribute and add the Claim to match the Discriminator and the role's Name.

Many domain models sharing one data context in EF 5

I recently, out of ignorance and lack of time, merged the domain models (POCO entity classes) from several projects into one 'DataModel' project, because I didn't want to duplicate dedicated DbContexts over all the projects. It struck me as ideal that something generic might be done, like a DbContext extension, to which one can add DbSet instances from various client projects.
I have read mention of such things, normally in the same circles as authors that contend - and I agree wholeheartedly - that the repository functionality is fulfilled completey by the DbSet class.
Can anyone offer any advice for building a generic DbContext which can exist in one project, where other projects can all have their domain models (sets of domain entities) registered with the shared DbContext, where they are all allocated they own DbSet to act as their repository?
building a generic DbContext which can exist in one project, where other projects can all have their domain models (sets of domain entities) registered
Interesting idea, but I'm not sure what you would gain by that.
For one, you'd never be able to simply type db.Customer (or similar). It should always be genericdb.Set<Customer>(), not knowing whether genericdb knows about Customer at all. (It may not have been registered).
Then, how should this registering take place? There are two ways to let a context map a class to a database model:
Creating a DbSet property in a DbContext-derived class and rely on code-first default conventions concerning table and column names, pluralization, etc.
Providing mapping configuration.
The first option defeats the purpose of a generic context class, so you'd have to register the domain classes by supplying EntityTypeConfiguration<T>s for each class in the domain, also for classes that normally could do without. (This should be done in the context's constructor, by the way.)
A further implication would be that somewhere you'd need a component/service that knows which groups of classes belong together and is able to deliver a coherent list of configurations. So, in stead of having dedicated contexts as an organizing principle out of the box you'd have to create your own organizer.
But back to the start. Couldn't you create a DAL that contains a DbContext factory that supplies the contexts as they previously existed for your projects? You don't have to duplicate dedicated DbContext classes this way.

Restrict access to database resources in Entity Framework + UoW + Generic Repositories

I'm using ASP.NET MVC3 with Entity Framework 4.
I am using the Unit Of Work + Generic Repository pattern.
I searched for similar question everywhere, I see that many people have my problem, but still can't find a good and practical solution.
We have a multi-tenant database.
Imagine a database with a similar structure:
customers
groups, associated to a customer
users, associated to one or many groups
And then, for each customer we have
resources, associated to one or many groups, and linked between each other with foreign keys, many-to-many relationships and so on
So, when a user logs in, he is associated to one or many groups, and he needs to have access to the parent and child resources associated to that groups.
Now the problem is:
I implemented a sort of pre-filtering with a .Where() clause into the unit of work, in the repositories, based on the id of the logged in user.
And this is working.
The pre-filtering I did on the repositories is working fine, but of course it works only if you access directly the repository of the sources of TYPE A or TYPE B or TYPE C and so on.
But a resource is linked to other resources with many-to-many tables and foreign keys.
So, it happens that sometimes a resource belongs to a group to which the user has access, but sometimes the resources linked to this resource belong to a group to which the user does not have access.
If I traverse the navigation properties of the "parent" resource, the user can access all the linked resources, even the one belonging to other groups.
So, if you are starting from a TYPE A resource, and traverse the navigation properties to reach the TYPE B and TYPE C resources, they are not filtered.
If you access the TYPE B and TYPE C repositories, they are filtered.
Now my filters, as I said before, are in the Unit Of Work class, but I tried to move them into a custom DBContext, applying the filters directly into the DBSet, but nothing changes:
It seems that EF is accessing directly the database to build the navigation properties, thus not using the other repositories or the other DBSet, avoiding the prefilter.
What can we do?
I see that NHibernate has Global Filters that could accomplish my task, so I'm evaluating a migration from EF to NH.
I see that many other people is asking for .Include() filters, thus disabling lazy loading.
Thank you.
I can provide some piece of code if needed, but I hope I explained my problem correctly.
Thank you i.a.
Best Regards,
Marco
I saw a solution with mapping to views and stored procedures, but I'm not sure how hard it was in development and maintanace. In short, it is possible to map EF model to views, where data will be filtered; in this solution each user have own database credentials.

Entity Framework Repository Design, multiple instances of IUnitOfWork in multi-level loop

i am using Entity Framework and repository with unit of work design pattern.
Sometimes with my unit of work, I am making other calls to a different service.
This service in turn is making its own unit of work instance, for example:
ISettingsService settingsService = UnityContainer.Resolve<ISettingService>();
using (IUnitOfWork unitOfWork = UnitOfWorkFactory.CreateUnitOfWork())
{
List<Company> companies = unitOfWork.CompaniesRepository.GetAll();
foreach(Company company in companies)
{
settingsService.SaveSettings(company, "value to set");
company.Processed = DateTime.UtcNow();
}
unitOfWork.Save();
}
// ISettingsService.SaveSettings code in another module...
ISettingsService.SaveSettings(Company company, string value)
{
using (IUnitOfWork unitOfWork = UnitOfWorkFactory.CreateUnitOfWork())
{
Setting setting = new Setting();
setting.CompanyID = company.CompanyID;
setting.SettingValue = value;
unitOfWork.Insert(setting);
unitOfWork.Save();
}
}
The above code does work, but i have to reference ID's explicitly rather than attaching the company object (it would throw an error as it is already being tracked by the other unit-of-work in the other service).
As far as I can tell I see 3 ways of this happening:
1) Use the code as-is with service layers creating their own unit-of-work instances, any other references to other entity's are done on a primary key basis (procedures to set values should be passed by primary key object value, i.e. int customerID).
The bad side to this is potentially more hits to the database, and if the entity primary key type changed, i would need to change all service layer references for the ID field.
__
2) Have service layers accept entity objects as references. This would be nice as i could pass objects around.
The bad side to this is that entities must not be referenced from any other context and must be attached to context to where it will be used. In a loop, the entity will most probably already be attached.
__
3) Pass in unit-of-work instantiations to other service layers to they can use the existing unit-of-work instead of instantiating their own.
Not sure there is a downside to this other than having to pass around a unit-of-work reference, the upside would be the ability to reference objects without having to attach them or worry if they are already attached.
__
In summary, I need to standardize on one access design, and would appreciate recommendations on what one i should choose.
In addition is there anything with transactions that i need to be concerned about or is EntityFramework with the unit-of-work design pattern implementing a form of transactional processing implicitly as changed are only committed on context.Save(), or am i mistaken?
Thanks,
Chris
You have a few options amongst them:
Have different services pass out dettached entities (its entities), perhaps even DTOs that are not entities, then have each service translate them to its entities (or use primary keys).
Each service can create its own content and use its own EDMX or a shared EMDX (or even several EDMXs).
If the services are using the same EDMX, then inject the same context into them (you can wrap it behind and interface so that they don't expose EF).
If the services don't use the same EDMX, either:
3.1. Go with option 1, using different entities for different services (or DTOs).
You can "share" tables between the EDMXs using different entities or use views to "tables from external domains" to reflect a read-only version of tables to other domains.
3.2. Create a master EDMX by merging the EDMXs into one big one (see this question for details)
Changes are applied only when calling context.AcceptChanges(), so you can save changes to multiple contexts, then accept changes in each after all the saves have completed.

Change Fluent API mapping dynamically

Our project uses Entity Framework Code First. We wish to have an instance where a very simple POCO represents many tables in the database. It is part of a horizontal partitioning strategy in SQL Azure. SQL Azure does not support file groups, thus it does not support typical partitioning. There are going to be a very large numbers of tables, so using a UNION ALL view as a partitioned view via CHECK CONSTRAINTs on the base tables will not be feasible.
Thus, we would prefer to peform the mapping as needed at runtime. However, this occurs in the OnModelCreating event of the DbContext class via code such as
modelBuilder.Entity<EntityName>().ToTable("foo", "bar");
. Is it possible for us to perform this mapping inside a factory? We would prefer to supply metadata to the factory and have it use the Fluent API then, rather than have a one-to-one mapping between POCO and table via the ModelBuilder.
You can add a constructor to your DbContext derivative, having two string arguments for table name and metaschema name. You can store the names in member variables and use them in the ToTable method.
The DbModel is created when it is actually needed, so the constructor always runs before the OnModelCreating event. (This is not always the case in derived classes, but that's a different topic).
As an optimization you can cache compiled DbModels and build DbContexts by the constructor accepting a DbCompiledModel.