Entity Framework inheritance over different assemblies - entity-framework

I'm quite new to Entity Framework, but the more I worked with it, the more I actually liked it. But now my passion is at risk, as I'm struggeling with an issue that already made me crush my head against the wall.
The problem is the following:
I'm using Entity Framework 5.0 with code-first approach plus inheritance for my business models represented by Table Per Hierarchy. At first I had all of my entity types, that were supposed to be mapped, in the same assembly as my DbContext (which worked fine for both TPH and TPT). But as they also contain logic that is dependent on other assemblies, this turned out as no good approach since it caused circular dependencies because those assemblies also need to have knowledge of the Data Access Layer, which in turn has to have knowledge of the entity types that it is supposed to map).
I solved this issue by introducing a CommonObjects project, where I now keep all of my abstract classes and stripped out the concrete descendents (containing the logic, etc.) of those base classes into the specific projects, which are responsible for them.
(see: Circular Dependency Solution)
It compiled and everything seemed to fit the way I imagined it.
But now it turned out that Entity Framework seems to struggle with the derivates being in a different assembly than the base classes.
During runtime, when trying to access the DbContext the first time, the compiler threw an InvalidOperationException saying:
The abstract type 'Foo.Bar.AbstractClass' has no mapped descendents
and so cannot be mapped. Either remove 'Foo.Bar.AbstractClass' from
the model or add one or more types deriving from
'Foo.Bar.AbstractClass' to the model.
So EF is obviously not able to find the descendents, as it only knows the base classes (which are in the CommonObjects project), but the descendents are in a different assembly.
DbSet<AbstractClass> AbstractClasses { get; set; }
According to this question:
Entity Framework Code First and Multiple Assemblies
I tried to add the following code to the constructor of my derived DbContext:
((IObjectContextAdapter)this).ObjectContext.MetadataWorkspace.LoadFromAssembly(
Assembly.Load("Foo1"));
But that did not work for me. While debugging and watching the MetadataWorkspace the method "LoadFromAssembly" did obviously not have any effect on the MetadataWorkspace and its items (no types were loaded from assembly Foo1).
What am I missing here?
Thanks for your answers in advance.
Ben

EDIT: This only barely works and isn't worth it, and doesn't work at all if you're using CodeFirst.
I have encountered the same issue with code first. I tried your method of reflection. This seems a bit wonky, but you can trick EF into being okay with your set up with an internal class.
internal class ClassToMakeEFHappy : AbstractClass {}
I just created that in the same file as my AbstractClass definition and it did the trick.

Related

How to disable automapping of properties in Entity Framework

I've decided to use fluent mapping in Entity Framework. My intention was to map everyting by code without any atributes and auto mapping functions. Best way I've found is class EntityTypeConfiguration, that I implement for each entity in my project.
Later I add property to one of my entity. This property isn't needed to be persisted. I've expected, that until I add mapping for this property, it will be ignored by database and persistence layer. Unfortunatly it doesn't work that way, and property is mapped. Only way is to use Ignore method or NotMapped attribute, but I don't want to do it explicitly.
Is there any way, to stop Entity Framework from automapping? I've tried to remove all Conventions from DbModelBuilder, but it doesn't help.
So far as I am aware, there is no other way around it. You need to use either Ignore() or [NotMapped]. I tend to prefer the former as it does not clutter up the model.
Actually I have tried a lot of ways:
- custom convention to remove mapped properties
- removing all conventions
But the easiest (and cleanest) way was to use reflection inside the mapping class and to disable all property mappings that weren't configured.
The code for that (and also an usage example) is inside my public gist.
https://gist.github.com/hidegh/36d92380c720804dee043fde8a863ecb

Entity Framework 5 model first - Where is IDisposable gone?

In Entity Framework 5 model first, there seem to be some breaking changes due to the way the class files are generated (No more code generation, but T4 templates)
2 examples:
The generated context file doesn't implement IDisposable anymore
There isn't a constructor which takes a connectionstring anymore
Are there more breaking changes? And what is the solution to them?
The default code generated from a model in Entity Framework 5 now inherits DbContext instead of ObjectContext.
This still implements IDisposable, but if you're getting an error from a line of code similar to this:
using (var mymodel = new MyModelContext()) { ... }
...complaining about not implementing IDisposable, then your problem is most likely that your model is defined in a separate assembly that references EF5 and you have not added an EF5 reference to your project.
As Ladislav Mrnka has already mentioned in his answer, if you want to pass a connection string to the constructor you have to create your own constructor manually to do this.
If you want to switch Entity Framework back to the older style of generated code, which will automatically generate the constructor you're looking for, then follow these steps:
Click on the designer surface of your EDMX file, and look at the properties window. Find a property called "Code Generation Strategy" and set this to "Default" instead of "None". This will tell Visual Studio to start creating the code for your object model in MyModel.Designer.cs in one big file, this time using ObjectContext instead of DbContext.
Delete the following sub files from below your EDMX file: MyModel.Context.tt, MyModel.tt. These are the auto generated files that you don't want anymore. If you don't delete them you'll get class naming conflicts because your objects will be created twice.
The generated context file doesn't implement IDisposable anymore
IDisposable is still implemented by the parent context type. The generated type is still disposable.
There isn't a constructor which takes a connectionstring anymore
It now uses convention to get connection string but you can add your own constructor either to template or to your partial class part of the context.
Are there more breaking changes? And what is the solution to them?
It is whole breaking change because it uses different API - DbContext API instead of ObjectContext API which means different types, different methods, POCO entities etc. If you want to get back to original code generation you have to delete those T4 templates and enable code generation as described in .Designer.cs file but the current recommended way is to use POCOs and DbContext API.
I was having the same issue with the using statement needing a type that extended IDisposable... Turns out that I forgot to reference System.Data.Entity in my project... Added the reference and it fixed the problem.
Just clean and build the project, don't forget to add the reference to your entity.

EntityFramework 4, DbSet and ObjectContext

few days ago i read tutorial about GenericRepository and Unit Of Work patterns http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application. I use web forms and i have EntityFramework CTP4 package installed. (I can't using EF 5).
I want to code generic repository for my project but i was stuck at this line:
this.dbSet = context.Set<TEntity>();
I know that this line doesn't work because a use ObjectContext in my project and database first approach. How can i deal with it? Can I code generic repository without migration to code first (which is not an option in my case) ?
This is the equivalent for ObjectContext:
this.dbSet = context.CreateObjectSet<TEntity>();
Now this creates an ObjectSet<TEntity> rather than a DbSet<TEntity>, but for your pattern you can use it in the same way.
UPDATE
The ObjectSet class does not have a utility method like that matches the Find() method of the DbSet. In order to "Get by key" you would need to construct an EntityKey and use the ObjectContext.GetEntityByKey(), unfortunately that's not a really simple thing to do.
There really isn't a simple way to tackle this, that I've found. In my case what I've done is to base all of my entities from a common class (using custom T4 templates to generate the classes from the model). And then I can add a generic constraint to my repositories, like:
public class MyRepository<TEntity> where TEntity : MyEntityBaseClass
And then my common base class has an Id field which is inherited by all the entities so I can can simply do:
return myObjectSet.SingleOrDefault(x => x.Id == myId);
I'm sure there are other approaches, that might be a good topic for another question.
1. You want to add the DbContextGenerator template to your visual studio templates:
2. After this make sure you clear out the default generation tool on your .edmx file.
3. Now you can implement the GenericRepository pattern as you wish.

Entity Framework Code First and Multiple Assemblies

I have a subclass in a different assembly to its base class. The parent is a POCO class used for EF Code First.
When I try to add an instance of inherited class to the database I get InvalidOperationException: "Object mapping could not be found for Type with identity 'Foo.Bar.MyInheritedClass'".
It works fine if subclass is in same assembly as base class.
In regular EF the solution seems to be a call to ObjectContext.MetadataWorkspace.LoadFromAssembly(assembly). But I can't figure out how this relates to Code First.
Any advice?
I'm using Entity Framework 4.1 RC.
I solved this by inheriting from the first assembliy's DbContext, adding a DbSet<> for the derived class, and then adding new instances of derived type to to that.
Posted code on MSDN forum here.
I know this post is a bit old, but I was able to accomplish this using #Dave's recomendation inside the constructor:
public Context() {
((IObjectContextAdapter)this).ObjectContext.MetadataWorkspace.LoadFromAssembly(
System.Reflection.Assembly.GetAssembly(
typeof(--[Inherited DbContext]--)));
}
I'm quite new to EF (Entity Framework 4) and I got the same exception when I made changes in the model.
My problem turned out to be that I did not know EF need all the names on all the navigation properties to agree, not only their type. For example if there is a navigation property named foo, then there needs to be a declared variable in the corresponding class with the very same name.

Inversion of Control, Dependency Injection w/SRP, and Lazy-Loading

A fellow developer and I are conversing (to put it lightly) over Lazy-Loading of Properties of an object.
He says to use a static IoC lookup call for resolution and Lazy-Loading of objects of an object.
I say that violates SRP, and to use the owning Service to resolve that object.
So, how would you handle Lazy-Loading following IoC and SRP?
You cannot Unit test that lazy-loaded property. He rebuttles that one saying, "you already have unit tests for the UserStatsService - there's your code coverage." A valid point, but the property remains untested though for "complete" coverage.
Setup / code patterns:
Project is using strict Dependency Injection rules (injected in the ctors of all services, repositories, etc).
Project is using IoC by way of Castle (but could be anything, like Unity).
An example is below.
public class User
{
public Guid UserId { get; set; }
private UserStats _userStats;
// lazy-loading of an object on an object
public UserStats UserStats
{
get
{
if (_userStats == null)
{
// ComponentsLookup is just a wrapper around IoC
// Castle/Unity/etc.
_userStats =
ComponentsLookup
.Fetch<UserStatsService>()
.GetByUserId(this.UserId);
}
return _userStats;
}
}
}
The above shows an example of lazy-loading an object. I say not to use this, and to access UserStatsService from the UI layer wherever you need that object.
EDIT: One answer below reminded me of the NHibernate trick to lazy-loading, which is to virtualize your property, allowing NHibernate to create an over-load of the lazy-loading itself. Slick, yes, but we are not using NHibernate.
No one really tackles the matter of Lazy-Loading. Some good articles and SO questions get close:
Using Dependency Injection frameworks for classes with many dependencies
http://blog.vuscode.com/malovicn/archive/2009/10/16/inversion-of-control-single-responsibility-principle-and-nikola-s-laws-of-dependency-injection.aspx
I do see a benefit of lazy-loading. Don't get my wrong, all I did was lazy-loading of my complex types and their sub-types until I switched to the D.I.-ways of the ninja. The benefit is in the UI layer, where a user's stats is displayed, say, in a list with 100 rows. But with DI, now you have to reference a few lines of code to get that user stats (to not violate SRP and not violate the law-of-Demeter), and it has to walk this long path of lookups 100+ times.
Yes yes, adding caching and ensuring the UserStatsService is coded to be used as a Singleton pattern greatly lower the performance cost.
But I am wondering if anyone else out there has a [stubborn] developer that just won't bend to the IoC and D.I. rules completely, and has valid performance/coding points to justify the work-arounds.
Entities themselves should not have the responsibility of lazy loading. That is an infrastructural concern whose solution will lie elsewhere.
Let's say an entity is used in two separate contexts. In the first, its children are used heavily and are eagerly-loaded. In the second, they are used rarely and are lazy-loaded. Is that also the entity's concern? What would the configuration look like?
NHibernate answers these questions by proxying the entity type. A property of type IList<Entity> is set by the infrastructure to an implementation which knows about lazy loading. The entity remains blissfully unaware. Parent references (like in your question) are also handled, requiring only a simple property.
Now that the concern is outside the entity, the infrastructure (ORM) is responsible for determining context and configuration (like eager/lazy loading).