Supporting default column values in custom Entity Framework provider - entity-framework

I'm working on a custom entity framework provider and I need to add support for default column values for this provider. When the user uses the entity framework wizard and selects a table that includes columns with default values, those default values are not being populated into the entity designer.
I'm a little lost on where exactly this population should take place. I believe the appropriate place would be in the GetEdmType method override of DbXmlEnabledProviderManifest but I just don't see how to set the default value, if this is the correct place.
Anybody has experience writing EF providers that support default values for table columns? How do you implement this?

I am a bit late to the party but DbXmlEnabledProviderManifest is not the right place for adding default values. The provider manifest describes capabilities of the database engine itself and is specific (and general) to this database engine and not to a given database and/or table. The default value in the provider manifest tells EF what value to use for the given column property if one is not provided by the user (e.g. if the user user does not specify scale or precision for a decimal column the value from provider manifest will be used for scale and/or precision used for this column).
If you want just to insert a default value for a property the easiest way is to set the property that corresponds to the column on your entity to this value in the constructor. This way the user can always set it to a different value but if s/he does not the default value will be sent to the database. For some corner case scenarios where some of the columns in the database do not have corresponding properties on entities you can use DefaultValue attribute on the Property element in SSDL which will be inserted to the database when you add a row. This is especially useful if those properties are not nullable since without telling EF what value should be inserted EF would try inserting null which would obviously fail for non-nullable columns.

Related

Multiple Table Versions

I'm looking for a little "magic"
We have multiple applications written using entity framework. We need to update the scheme of a couple of columns - basically increasing the size of some account numbers columns. In our situation, we host the application for other customers and do not wish to increase the size of their account numbers but would like to have a single entity framework implementation for both.
The logic is the same with both tables - only the field length changes. This is a very large code base and refactoring, rewriting etc. the ideal solution.
Is there a way to specify in a config file what the field length is so it can be built at runtime?
Application
Table
Customer Name (256)
Account NUmber (10)
Same Application
Table
Customer Name (256)
Account Number (18)
You can write your own custom validation attribute with EF like in these examples: Custom validation attribute that compares the value of my property with another property's value in my model class
Pass variable data to ValidationAttribute
You can read your CustomerName property value, and based on the data you can validate your AccountNumber property. And in this custom validator you can read your config file.

Why does the `DatabaseGeneratedOption.None` exist?

This is used with the Property(() => p).HasDatabaseGeneratedOption() call. Is is perhaps to turn off default DB value generation?
EF uses DatabaseGeneratedOption to figure out what to do with the value of a key column for new entities. If the DatabaseGeneratedOption is Identity EF knows that the value the property is set to can be ignored and that the one that comes from the database should be used. If the DatabaseGeneratedOption is None EF will insert the value of the property to the database as the value of the key column.
In Code First - when Code First conventions find an int property that can be the key property for the given entity they by default will configure this column as identity column (meaning the database will generate the value of the key column/property). DatabaseGeneratedOption.None allows you to overwrite this if you want to set key values on your own.
Its effect is to configure EF to not fetch a new identity value after inserting into the database.

EF CodeFirst: Rails-style created and modified columns

Using Entity Framework CodeFirst, how do I create a created datetime column that gets populated with the current timestamp everytime a record is inserted for that table, and a modified datetime column that has a timestamp generated evertime a row is updated? Rails does this by default and I was hoping the EF generated database would have this as well, but it doesn't. Is this something that can be done with data annotations? If so, how?
Thanks!
It is not supported in EF. EF will not create these columns for you automatically. You must do it yourselves by either:
Have Created and Modified properties in every entity where you want to maintain these values. You must also manually maintain these columns in your application (common approach is overriding SaveChanges and set values accordingly).
If you don't need these values mapped (you never expect to use them in your application and you are happy with the logic in the database) you can create custom database initializer which would execute your custom SQL to alter tables and add those columns, default constraints for Created columns and update triggers for Modified columns.

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.

EF Table-per-hierarchy mapping

In trying to normalize a database schema and mapping it in Entity Framework, I've found that there might end up being a bunch of lookup tables. They would end up only containing key and value pairs. I'd like to consolidate them into one table that basically has two columns "Key" and "Value". For example, I'd like to be able to get Addresses.AddressType and Person.Gender to both point to the same table, but ensure that the navigation properties only return the rows applicable to the appropriate entity.
EDIT: Oops. I just realized that I left this paragraph out:
It seems like a TPH type of problem, but all of the reading I've done indicates that you start with fields in the parent entity and migrate fields over to the inherited children. I don't have any fields to move here because there would generally only be two.
There are a lot of domain-specific key-value pairs need to be represented. Some of them will change from time to time, others will not. Rather than pick and choose I want to just make everything editable. Due to the number of these kinds of properties that are going to be used, I'd rather not have to maintain a list enums that require a recompile, or end up with lots of lookup tables. So, I thought that this might be a solution.
Is there a way to represent this kind of structure in EF4? Or, am I barking up the wrong tree?
EDIT: I guess another option would be to build the table structure I want at the database level and then write views on top of that and surface those as EF entities. It just means any maintenance needs to be done at multiple levels. Does that sound more, or less desireable than a pure EF solution?
Table per hiearchy demands that you have one parent entity which is used as base class for child entities. All entities are mapped to the same table and there is special discriminator column to differ type of entity stored in database record. You can generally use it even if your child entities do not define any new properties. You will also have to define primary key for your table otherwise it will be handled as readonly entity in EF. So your table can look like:
CREATE TABLE KeyValuePairs
(
Id INT NOT NULL IDENTITY(1,1),
Key VARCHAR(50) NOT NULL,
Value NVARCHAR(255) NOT NULL,
Discriminator VARCHAR(10) NOT NULL,
Timestamp Timestamp NOT NULL
)
You will define your top level KeyValuePair entity with properties Id, Key, Value and Timestamp (set as concurrency mode fixed). Discriminator column will be used for inheritance mapping.
Be aware that EF mapping is static. If you define AddressType and Gender entities you will be able to use them but you will not be able to dynamically define new type like PhoneType. This will always require modifying your EF model, recompiling and redeploying your application.
From OOP perspective it would be nicer to not model this as object hiearchy and instead use conditional mapping of multiple unrelated entities to the same table. Unfortunatelly even EF supports conditional mapping I have never been able to map two entities to the same table yet.