Map model constructor with Entity Framework Core - c#

Is there a way in EF7 to force DbContext to create instance of my model by passing values to constructor not assigning them directly to the properties?
Docs tells me that I can interact with EF by providing it services. I found that IModelCustomizer is responsible for controlling how a model is created. But I'm not sure that if that is what I'm looking for nor how to implement that.

Related

Do I need entity data model in OnModelCreating for runtime DB context?

So, I'm using EF DbContexts in the following way. One AppDbContext is an abstract class derived from DbContext, it contains my DbSets and is used as a type to inject into services. Its "implementation" is like AppDbContextMySql, which is self-explanatory - it's derived from AppDbContext and handles the connection to the actual DB. There can be several such abstract/implementation pairs to separate the data tables, but usually, all of them point to the same actual DB instance.
Then I need to migrate it all, so I add a MigrationDbContext implementing all the datasets and all the entity configurations needed, namely composite primary keys which can only be configured in OnModelCreating override.
The question is, if I already have the data model configuration in MigrationDbContext, have applied the migration successfully to the DB, and it's DB's job to handle keys and indexes anyway, do I need to have the model configuration in my actually consumed AppDbContext or AppDbContextMySql? In other words, is the model only used to generate migration scripts, or is it also needed at runtime to help EF handle the data in any way?
The short answer is yes, the model is definitely needed in all the cases.
Generating migrations from it is just one of the possible usages, and for sure not the primary - migrations are optional feature which may not be used at all.
The primary purpose of the model is to provide the mappings between the data (objects, properties, navigations) and the storage (database tables, columns and relationships). It is basically the M part of the ORM (Object Relational Mapper) what EF Core is.
It controls all EF Core runtime behaviors - LINQ queries, change tracking, CUD etc. Like what is the associated table/column name, what is the PK/FK property/column, what is the cascade delete behavior, what is the cardinality of the relationship and many others.
The way you asked the question makes me think you are assuming that the model is used just for migrations while at runtime EF Core takes that metadata information from the actual database. That's not the case. For EF Core the database is whatever you told them in the model configuration. Whether the physical database is in sync (correctly mapped) is not checked at all. That's why people start getting errors for non exiting columns in their queries when they screw-up some fluent configuration, or more importantly - do not include such.
Which is the main drawback of using separate (a.k.a. "bounded") contexts for a single database. Because having a DbSet type property in the derived context is not the only way the entity is included in the model. In fact typed DbSet properties are just for convenience and are nothing more than shortcut to the DbContext.Set<T>() method. A common (a sort of hidden) method of including entity in the model is when it is referred (either directly or via collection) by another already included entity. And all that recursively.
And when the entity is included in the model, it needs the associated fluent configuration regardless of the concrete context class. Same for referenced entities, and their references etc.
So I don't really see the benefits of "bounded" context classes - they probably work for simple self containing object set with no relations to other (and vice versa), but can easily be broken by this automatic entity inclusion mechanism.
For reference, see Including types in the model and Creating and configuring a model.

How does Entity Framework Core implement code first?

I’m trying to learn how Entity Framework core uses C# classes to create the DbContext model. I assume it discovers types based on DbSets then calls the same model builder that is passed to OnSchemaCreating, I just can’t find the code/logic in the repository that does this (or perhaps there is another approach). Can anyone explain how this is done and point to the source code that does this?
Smit Patel from the ASP.NET team pointed me to the answer. There is a ModelSource abstraction that takes both a DbContext as well as some conventions. It customizes the the model based on DbSets on the DbContext class by simply adding an entity type for each DbSet, the remaining property/key/index configurations are all done by conventions.

Add Entity Framework Data Annotation to Another Project's Class

Let's say I have a set of classes that I want to share across multiple projects. For instance, I could use them in a REST service and also in a client that consumes that service.
So I create the following projects:
MyOrders.Models
MyOrders.RestApi
MyOrders.Client
Both the RestApi and Client projects have dependencies on the Models project.
The RestApi is using Entity Framework (code first) so normally you'd decorate the model's properties with things like [NotMapped] and [Key]. However, I don't want the Client solution to have any dependency on Entity Framework. None. So I can't decorate the models' properties with EF-specific attributes.
So my question is, is there some way to correctly set the models' EF-specific attributes from the RestApi project instead, maybe in the Context's constructor or something?
You can have the POCOs in your Models project, keep them totally ignorant of Entity Framework, and do the mappings in a separate project or in the RestApi project itself.
You can do this by the fluent mapping API, for instance in the OnModelCreating override of the context that you create in the EF-aware project:
modelBuilder.Entity<Order>().HasKey(o => o.OrderID);
modelBuilder.Entity<Order>().Ignore(o => o.OrderTotal);
etc.
This is a good argument for using custom Data Transfer Objects that are independent of the table-like entities. Although it can feel like overkill to have nearly duplicate classes - one as DTOs and one as EF Entities - there is another long-range benefit: the two sets of classes can vary independently. Let's say that you change the table table structure, but the client doesn't need to know about this change. Update the EF Entity but you leave the DTO alone, though you may have to update how you map from EF to DTO.
Speaking of mapping: EmitMapper can be a great help in transferring between the two types of objects.
You need to split your data access models from the rest of the application using Data Transfer Objects.
This will give a lot of benefits. At first it will look if your duplicating all the code of the model. But when your application grows, you will find that need the data in a view which is formatted in another way than how it was or is stored the database. Validation attributes can be added in a very specific way just the way you need it.
Mapping in between them can be done various ways. By hand or by using a tool like AutoMapper

Ramifications of using DBContext with Dependency Injection

I'm still kind of new to using dependency injection to manage my DBContext in an ASP.NET MVC application I'm writing.
I'm attempting to follow the approach outlined in the article Managing Entity Framework DbContext Lifetime in ASP.NET MVC. Basically, this approach says to use Ninject and dependency injection and to add my DBContext as a parameter to the constructor in my controllers.
Further, I am implementing this in a base controller, or which all my controller classes will be derived.
This is working, but I'm hitting on the following issues.
This approach requires that every derived controller class also implements a constructor that accepts any arguments requires by my controller base class. Not only does this seem like a lot of extra typing that I must remember to add to any new derived class, but it also means that if I change the data passed to the constructor then I must modify the constructor in every derived controller class.
This gives me a DBContext for all my controller classes. But what about other classes in my model that need the DBContext? Should I need to manually pass the instance to the DBContext to all these classes? Or is there a way to use DI for each of these classes to get their own copy of the DBContext?
This approach requires that every derived controller class also
implements a constructor that accepts any arguments requires by my
controller base class. Not only does this seem like a lot of extra
typing that I must remember to add to any new derived class, but it
also means that if I change the data passed to the constructor then I
must modify the constructor in every derived controller class.
This is one of the approach (Heavy Controller) that you may choose to use EF into your application, IMO its not the cleanest approach. And you correctly noticed the drawbacks your self.
If we relate this approach to design principle, it breaks Single Responsibility Principle as controller is expected to do more (fetch or update DB) than just collecting the data and return the appropriate view with data. And how about business rules, would controller apply it, if you need to send an email, would controller does that as well. You ought to have another layer of business/service classes that are specifically designed for a set of requirement e.g. EmailHelper would send emails.
It also breaks Open Close Principle as you need to change the constructors every time you change the input parameter.
This gives me a DBContext for all my controller classes. But what
about other classes in my model that need the DBContext? Should I need
to manually pass the instance to the DBContext to all these classes?
As far as dependency injection is concerned one of the goal is, to inject the dependency where it is needed directly. If you have a model class that needs DbContext, you should inject it in your model class constructor (most DI framework support property injection as well but constructor remains favourite approach).
With DI Framework, you will configure the dependencies at one place (application initialization code) and then each class that need a dependency just accept it in constructor.
DI Container can be compared to a dictionary where key is interface and the value is a cooked object. Once its setup, you can anytime ask for any object by using the right key through out your application.
Or is there a way to use DI for each of these classes to get their own
copy of the DBContext?
The DI framework supports different ways of instantiation to allow controlling the lifetime of the instance. Typically, per request, per thread and singleton. More information here. If you want each controller to get a copy of DbContext, you can use per request configuration when you set up DbContext instantiation.
Alternate Solution:
Most of my MVC applications, I have had a service layer (set of classes that apply business rule). Each of these classes were injected with DbContext (not exactly a DbContext but IDataContext). The controllers were injected with the service class that they need to retrieve or update the data.
Have abstracted the DbContext behind IDataContext, I could setup a stub data context in my test or tomorrow if I want to switch from EF to NHibernate or something more smart DI Framework, i will just have to implement IDataContext and change the dependency initialization code.
Hope this helps.

Entity Framework 4 - Embed ObjectContext reference within generated Entities

I am new to Entity Framework 4.0, using it with C#, and currently experimenting with its features.
What I noticed is that, like with most similar ORMs, it relies on an Context object to deal with the data-manipulation and CRUD statements generation done on the generated entities.
This means that if I want to save the changes back to the database, I always need to be able to have access to a reference to the ObjectContext that has instanciated the entities.
It is fine and all if the context has been created in an accessable scope (same method, for example), but what if I pass an entity or and entity set to a method and want this method to save the changes? It looks like the only easy way is to pass the ObjectContext along with the parameters.
Another solution would be placing the ObjectContext in some sort of global variable.
Needless to say, I find styling and maintainability issues to both of these approaches.
In short, the best way I can imagine is getting a reference to the ObjectContext from the entity or entity set.
I know that it isn't possible by default.
I have found a method showing adding an extension method to get the ObjectContext from the entity. However, it only works for entities with relationships and calling this method is expensive according to the author.
I was thinking about maybe modifying the T4 template to add a Context property to all my entities and fill it automatically on entities' instanciation.
I have already modified T4 template once to have Entity Framework enforce Max Length on my generated classes (by following Julie Lerman's Programming Entity Framework 4 book).
I can't say I really enjoy the T4 syntax so far, but if that's the best/only way, so be it...
Has anyone already done so and what would be the best way to handle this and willing to share his T4 template or explain what are the best partial methods or events to hook into to get this done?
Is there any major downside in using such an approach?
I am thinking that having so many references to the ObjectContext may hinder/delay its ability to be recollected by the GC if some of my entities remain in scope but I actually have no use anymore for the ObjectContext.
Many thanks.
If you need to pass object context as parameter together with your entities you are doing something wrong.
Usually context is needed only in well defined layer. All classes from this layer which requires context to their logic can receive the context through some specialized class - context provider (it can also be called service locator). Context provider will hold current context instance in some storage - you can create your own or you can store it per thread, per http request, etc.
If they need more then one context instance in your classes you can modify your provider to work also as factory.
Another common approach is combined with dependency injection. You will pass the context to your classes through the constructor (or property) and you will have some bootstraper code which will do all necessary initialization for you (create required instances and pass all dependencies into them). Again you can pass a context or a factory. This is usually used together with IoC containers which will do the plumbing for you.
Once you have this infrastructure prepared you can pass your entity to the any initialized class from that layer and it will have the context available.

Categories

Resources