Converting Classes in Entity Framework - entity-framework

I'm using EF5 and Code-First.
I have an abstract base class called FooBase. Foo1 and Foo2 both inherit from FooBase. I use EF's mapping configuration based on a Discriminator called Bar. So if Bar = someValue, create Foo1... if Bar is anotherValue, create Foo2.
Since Bar is a discriminator, I don't have access to it as a property on any of the Foo classes.
I now have the need to convert an instance of Foo1 to Foo2. I use reflection and move the properites to the new instance, including Foo1's key value. It's an exact duplicate, except that it is a different type. I change the EntityState to modified and save to the database.
However, the discriminator value in the database is not getting updated. It still remains the same value as if it was still Foo1.
I can guess that since the enitity is only set to modified, EF doesn't bother checking the discriminator.
Does anyone know a way around this?

You cannot change existing instance to another type. Type of the entity associated with key value is immutable. If you want to create Foo2 from Foo1 you need to create a new instance with a new key value and insert it to database. Just modifying will always keep the key and discriminator.
If you seriously need to change the type and keep the key inheritance is not solution for you. Think about the key as equivalent to reference and about discriminator as equivalent to type in .NET - you cannot change type of existing reference.

Related

Discriminator Column Type

I've been looking at various Code First examples of TPT (Table Per Type) in Entity Framework.
I have an abstract base class with 4 concrete implementations, all of which share the exact same interface. These are being stored using EF in a single table named after the abstract base class.
What I wish to do is use the EF Discriminator column, but without using the automatic table creation in Code First, instead adding the configuration and mappings manually. Does anyone know if this would be possible and if so, what the type of the Discriminator column is (name, type, length, nullable, etc.) so I can create one manually?
Many thanks.

entity framework "composite" property?

I am using EF 4.1, code first and want a property on a customer entity built up of a constant string value and the customerId zero padded to act as a customer reference.
I might be being a bit daft but am struggling to work out how I can achieve this without
A) having to savechanges twice, once to get the Id then set my reference and save again
B) having a partial Customer class that simply provides a getter returning constant + CustomerId.Tostring("000000")
Is this "doable" with code first?
If you can change the database I would make a computed column for this. Thus, you leave it to the database to generate a reference value and it will also be available to other consumers of the database (if any).
Your Customer class will have a property like CustomerReference (string) that maps to the computed column and that is configured to have DatabaseGeneratedOption.Computed which will cause EF to read the value after inserting an object.

How to Use inheritance in EF

I am using EF 4.0 , i have one problem
Table structure in DB is:
Table: Setting--->
Name (PK)
GroupBy
DataType
Table: UserSetting-->
SettingName(PK)(FK)
UserName(PK)(FK)
Value
Table: WorkstationSetting-->
SettingName(PK)(FK)
WorkstationName(PK)(FK)
Value
Now i want to make use of inheritance, because WorkstationSetting and UserSetting inherits settings so any suggestion how to achieve inheritance, i tried but i got error like
"Error 39 Error 3003: Problem in mapping fragments starting at line 1621:All the key properties (Settings.Name) of the EntitySet Settings must be mapped to all the key properties (WorkstationSetting.SettingName, WorkstationSetting.WorkstationName) of table WorkstationSetting.
I see you have in UserSetting and WorkstationSetting a composite PK.
If UserSetting and WorkstationSetting are derived from Setting, they should have Name as PK.
Another comment; in general, it's not recommended to use a name or something "meaningful" as PK since it is less scalable and might cause limitations (i.e. max index size). Use instead an int or uniqueidentifier.
I recommend you to introduce a new field which is SettingId which should be added to all three tables. In EF designer, just add the Inheritance.
Look into table per type inheritance. For example look here. It should help you get started. The idea is that you have a table for each concrete type (as you have) and you map it to an object hierarchy.
Maybe your problem is with the keys. How is your mapping defined? Are the associations between the tables defined in the DB?

Entity framework 4 model first using money value object

I want to use a Money value object in my application. I have found several examples of a Money datatype. But I can't figure out how to use them with EF4. I would like to store each amount as a Decimal/CurrencyCode pair (where currencycode is a string - "USD", "SEK", etc) in the database. I tried creating a complexType but I couldn't get that to work. Is this possible?
It should be definitely possible. Your complex type is just pair of decimal and string property. It is exactly what complex type are used for. Depending on your approach you must do:
Database first:
You will define your database first. Your table will contain money and varchar columns representing your new type. When you update your EDMX model from database it will include it as scalar properties to your entity. You must remove those properties. Then go to model browser and create new complex type. Return back to entity and add complex property of your new complex type. And at the end you must go to entity mapping and map your complex type to those database columns.
Here is basic tutorial from MSDN but from unknown reason they didn't include such elementary details like screenshots. Here is some video from channel9.
Model first:
This is similar to database first but you don't have to deal with database creation and mapping. It will be generated for you.
Code first (EF 4.1):
You must create separate class for your complex type and use it as property in your entity. You should not need to map it by default - mapping should be infered. If it doesn't work you can map complext type either by using ComplextTypeAttribute annotation or by defining mapping in DbModelBuilder.
I can further extend approach you need to use if you provide more details.

Not nullable fields in table inheritance - EDM

I just read this nice article that taught me how to use inheritance (Table-per-hirarchy).
I was wondering, say I have a column 'HireDate' that need to use in the sub-class.
That's for sure that in the DB it has to marked as nullable, but how can I mark it not nullable in the EDM?
I tried to set it as not-nullable, but then it says that it needs a default value, and I want the default value to be DateTime.Now, not a constant value.
If a property (like HireData) is declared on a derived type and you are using TPH you should definitely be able to mark it as non-nullable in the EDM despite the fact it is nullable in the database.
In fact this ability is one of the characteristics of TPH.
...
So I looked at the blog post in question, and noticed it has a problem because it exposes the discriminator column (PersonCategory) as a property of the base Entity, which if allowed would make the type of an Entity mutable, since you could easily do this:
student.PersonCategory = 2;
Which would make Student an Administrator! And that is NOT allowed by the EF.
So if you are following this example closely that is likely to be your problem.
The column that holds the discriminator shouldn't be mapped to a Property in the EDM, it should only be used in the mapping (i.e. 'Add a Condition' under 'Maps to XXX' in the mapping window).
Solution to problem in Blog Post: Remove the PersonCategory property from Person class.
Anyway I hope this helps
Alex