Our organization is looking to standardize on Entity Framework once v4 comes out. As a result, I am looking at what it would take to migrate our application that uses NHibernate for persistence to EF4 using POCO support. In a couple of places we use single table inheritance (also known as Table Per Hierarchy). I have been unable to get it to work using the following.
Payment (base class [should be abstract but having trouble there as well])
CreditCardPayment (concrete implementation)
ACHPayment (concrete implementation)
CheckPayment (concrete implementation)
Right now, I am mapping them with only the base class properties. All of these classes are in the same namespace. They have a discrimimator that is called PaymentTypeId in the database, so the Payment mapping has a condition of "When PaymentTypeId = 0". Each of the subclasses have the same condition with different values (i.e. CreditCardPayment = 1, etc.).
When I try to load each a list of all payments using DataContext.Payments.ToList() (DataContext inherits from ObjectContext) I am getting the following exception:
"Object mapping could not be found for Type with identity 'DataLayer.DataModel.CreditCardPayment'."
I can't figure out what this means, as the POCO CreditCardPayment class lives in the same namespace as the POCO Payment class does (in fact in the same file).
What am I missing?
This is complaining not about database mapping, but model to CLR mapping.
The EF can't for some reason find your CreditCardPayment class.
Now one possible reason is that you haven't loaded the metadata for it yet.
For example if you have this:
Assembly 1:
- Payment
Assembly 2 references Assembly 1:
- CreditCardPayment extends Payment
Then when you query the EF doesn't know where CreditCardPayment lives.
The way to get around this is with LoadAssembly i.e:
using (DataContext ctx = new DataContext())
{
ctx.MetadataWorkspace.LoadFromAssembly(typeof(CreditCardPayment).Assembly);
// now do your query.
}
You need to tell to LoadFromAssembly every assembly that isn't directly reference by your DataContext class.
Note: typeof(Payment).Assembly is directly referenced because of the IQueryable<Payment> Payments property.
Hope this helps
Alex
Microsoft.
What I didn't represent before (I didn't think it relevant, but it was). Was that CreditCardPayment inherited from an intermediary class named "CreditPayment" and ACHPayment inherited from CashPayment. CreditCardPayment and CashPayment live in the same namespace and file, but were not represented in the EF mapping. Once I added those within the mapping file, everything worked ok.
So, even thought EF does not ever map to one of those types directly, it seems to need to know about them, because it changes the basetype of the CreditCardPayment classes et al. Thank you for your help on this.
Related
I implemented Windows Identity into my application and using EF Migrations the appropriate [AspNet*] tables were added to my database. As typical in this scenario, I created an ApplicationUser class that inherits from IdentityUser. My 'ApplicationUser' class does not have any additional properties. And at that point in time I did not touch any code or classes related to Roles.
Now I am looking to add roles so I followed the same pattern as before. I created an 'ApplicationRole' class that inherits from 'IdentityRole' but did not add any addition properties.
However, and this is where my question comes in, EF migrations is trying to create a [Discriminator] column for the AspNetRoles table. Yet it never created one for the AspNetUsers table in the previous migration.
I understand the purpose of the Discriminator column so I am not questioning why it is there. I just do not understand why it is adding it for one table and not the other when both base classes were inherited by the "application" equivalent classes.
The only plausible reason I can think of is because the original IdentityRole class was used in the earlier migration and now I am trying to add a new migration that uses the base class. If so, is there a way to get EF to ignore this? There are no plans to ever create multiple classes that inherit from the base nor will I be using the base directly so the Discriminator will always contain the same value.
I am doing a proof of concept in a line of business application where I want to swap out the current C# Code-First Entity Framework implementation with a F# one. I am following this article which seems to work pretty well, but I was hoping to use FSharp record types instead of the classes that the article uses. When I try and add a data annotation to a record type like this:
type Family = {[<Key>]Id:int; LastName:string; IsRegistered:bool}
I get the following error:
Error 1 The type 'Key' is not defined
Is there a way to use data annotations with record types? Apparently, EF Code-First needs annotations...
Record types support attributes just fine (and with the syntax you have).
Check if your reference to System.ComponentModel.DataAnnotations is in order, that's where KeyAttribute is defined.
Edit: EF wants to work with properties, that's why using a record doesn't mesh well with EF. You can still make it work in F# 3.0+ by marking the record with CLIMutable attribute (this generates property setters and a parameterless constructor which are taken for granted by C#-centric frameworks and libraries).
The article you're looking at was written with F# 2.0 in mind - CLIMutable wasn't around yet and there was no way of using records for that.
So I have run into a situation where I need to use the Entity Framework (DbContext) with databases whose columns are not known at compile time. Basically I don't have the luxury of hard coding a customTable class to put into the DbSet.
The only thing I can think of for solving this issue is using Reflection.Emit to create a customTable class at run-time based on information I glean by interrogating a database.
I was not able to find any information of solving this issue, but I am very new to working with the Entity Framework so maybe a solution would be more obvious to someone more experienced.
I feel like there should be a cleaner way than using Reflection.Emit to dynamically create a class to feed DbSet.
If I am way off base for the intended use of the Entity Framework that information would be useful as well.
Hi I'm investigating this problem too and I have found what seems like the solution.
http://romiller.com/2012/03/26/dynamically-building-a-model-with-code-first/
tells you how to make a DbContext into which you add a new DbSet using a type as a parameter. You can create this type using the Dynamic Linq Library:
http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx
It has a method called CreateClass which will allow you to dynamically build a POCO class definition from a list of field names and load it, you can then create a DbSet using the new type you have created.
You can then get a non-generic DbSet from your updated DbContext using
db.Set(type)
where 'type' is a variable holding your new type. This can be worked on using the linq predicates in the dynamic linq library.
Incidentally, my application is for a CMS where new modules can add fields to the core data table for the CMS, and I don't want to use DI as its too inflexible as no given module will be able to provide a type which has all the fields it needs and all the other unknown modules might also need.
James
I am facing a problem with EF 4.1. I am trying to Add a detached object to the DbContext. Problem is it is not the emd mapped object, but derived from it. Changing the mapping is not an option as some teams are using the model with the regular mapped BL-classes, but my project created a derived model for UI stuff. Even with casting I always receive a
InvalidOperationException ("Mapping and metadata information could not be found for EntityType ...").
What I want is EF to treat this as the base class and put the object into the DbSet of the BaseClass. The current EF code is:
Context.Entry(object).State = EntityState.Added
But I am open for other suggestions, even
via IObjectContextAdapter, as long as it can save the Base and the Supertype. This should be simple, right?! Mapping to a new Base-class instance is not good idea as the main objects temporary Id would not be updated after saving...
Thanks!
As I know this is not possible. You cannot use derived class from the entity instead of the entity. You must either map derived class as well or create new instance of the entity for persistence and copy all fields from your derived class instance to the entity instance.
I've tried to use Entity Framework 4 and POCO for my MVC 3 project. May be, I don't understand the main idea of this ORM, but the problem is following:
I added ADO .NET Entity Data Model and make model according to database.
I clicked Add Code Generation Item and added ADO .NET POCO Entity Generator.
It makes classes for every database table.
I want to add some methods to work with data (Add, Update, Delete, GetAll etc) to appropriate models.
For LINQTOSQL I added partial classes and placed them to Models. But now I can't do it because:
a) Models folder has classes with the same names, which was created by POCO.
b) If I place my partial class in the another folder, it will be another namespace - so, such classes won't be partial one.
c) If I place my code in POCO classes, it can be destroyed during update POCO.
How can I use it? Where sould I place my methods for data working?
Is the best way to make for POCO and EF the other project - http://blogs.msdn.com/b/adonet/archive/2010/01/25/walkthrough-poco-template-for-the-entity-framework.aspx?
First of all you don't have to write your CRUD inside POCO,
There are many places where you can do it like in edmx.cs file or write one more layer which is called as CRUD Services which handles the Database operations using context object.
Now coming to your questions,
Create separate Models folder and place the Model classes in there.
Your Model class may like this,
EmployeeDepartmentModel
{
prop EmpList List(Emp);
prop DeptList List(Dept);
//Emp and Dept are my POCOs
}
So now I have to fill both of these list(Your CRUD question),
For that, I will Create one method in Controller class(its better to write such logic in some another library, but for time being I suggest you to create in Controller),
FillTheModel()
{
EmployeeDepartmentModel.EmpList = EDMX.GetAllEmployees;
EmployeeDepartmentModel.DeptList = EDMX.GetAllDepartments;
}
Now you can bind this model with your view.
You can place the partial classes in another folder and modify the namespace.
I agree with allisewell, but if you really want to add parts to partial classes, give files another name,
e.g. MyPoco.Part2.cs or modify t4 template to name generated files
e.g. Poco.Generated.cs