EF partial classes and default values - c#

Following on from an SO dicsussion here, I have implemented partial classes so as to create default datetime values for my Created and Modified database fields in a Constructor.
Now the problem is that my database has 100+ tables, and 75+ of them have the same basic structure which includes a Created and a Modified column definition.
So.. Instead of creating 75+ partial classes which I need to maintain, is there any way I can create a base class which every EF type inherits from, which inherits the default constructor to populate the DateTime values for Created and Modified?
EDIT: Worthy of note is that I am using EF 4.0

You can certainly specify your own base class with both EF4 and EF1, though it's a lot easier with EF4. Right click on the design surface and you should see an option to add a Code Generation Item. Select the ADO.Net entity object generator. This will a T4 file to your project (.tt extension) that specifies the template to use to generate your entity classes from the model. To specify a different base class, look inside it for a line like
Private Function BaseTypeName(ByVal entity As EntityType, ByVal code As CodeGenerationTools) As String
Return If(entity.BaseType Is Nothing, "EntityObject", MultiSchemaEscape(DirectCast(entity.BaseType, StructuralType), code))
End Function
Replace EntityObject with your base class. Note that if you are using this template then your base class must inherit from System.Data.Objects.DataClasses.EntityObject - you could use a POCO template instead, but this will probably be enough for you.

You can certainly tell EF to use a base class for your entities (it's right in the designer as a property for the entity)...but if you want to make sure of the default value for this field, perhaps you could hook into the two events on your ObjectContext SavingChanges and ObjectMaterialized.
http://msdn.microsoft.com/en-us/library/system.data.objects.objectcontext.savingchanges.aspx
http://msdn.microsoft.com/en-us/library/system.data.objects.objectcontext.objectmaterialized.aspx
You could use these opportunities to inject the default value(s) that you want to use. So in your SavingChanges handler, for example, you could check the ObjectStateManager on the context to see if the state of the relevant entity is EntityState.Added, then set the Created and Modified dates as desired.
Alternatively, as suggested, is there a reason the default value for the column in SQL Server can't just be GetDate()? (Assuming you're using SQL Server)....

Related

How to set default values in Entity Framework 6 (Database First)

Background: I’m beginning a project to convert a web application using Linq2Sql to use Entity Framework (v6) instead. I have a lot of experience with L2S, but I’m brand-new to EF. Since our application and its database already exist, we’re using the “Database First” approach. Also, the database is evolving, so we’re making changes in the schema and the model is updated from the revised database, which regenerates code for the EF model each time.
For many of our entities (database tables), we set default values in our code whenever an entity is constructed. In Linq2Sql it’s easy: define a partial class for the entity, and add a method to the class like this:
partial void OnCreated() { SomeProperty = SomeDefaultValue; }
Whenever Linq2Sql constructs a new entity object, it calls the OnCreated() method you define, and the default values are set as desired. It works great.
The Problem: In EF, I don’t see a way to do this in a Database First scenario.
If I modify the model code generated by EF, the model code is overwritten whenever we update the model after a database revision.
If I define a partial class for the entity in a separate file and define a constructor, the compiler complains that the constructor is already defined.
There doesn’t seem to be any support for something like L2S's OnCreated() method, either.
Any suggestions?
EDIT: Thanks everyone for the helpful comments, but I think I need to point out an important consideration: My goal is to use the database-first approach and stick with it, rather than switching to code-first. When the database schema changes over time I want the EF Designer (or POCO Generator or whatever tools) to update my EF entity classes to match. All without losing my additions to initialize class properties when the class is constructed in the application. This is easy in Linq2Sql, but I just don’t see a way to accomplish this in EF database-first. All suggestions are welcome!
1 . Open .edmx file
2 . Select the field that has the default value and go to the properties
3 . then select StoreGeneratedPattern
4 . then change the value to Computed
i think it's worked.
OP here – I’ve given credit for the answer to ErikEJ but I’d like to recap what I’ve learned on this topic to share with others. There are three goals:
Use the database-first approach and stick with it, even as the database schema is changed over time. That is, have EF produce the code for each database table entity, based on a preexisting database, and update the code when the database is altered.
Provide a mechanism to initialize entity object properties each time the object is constructed, such as Employee.Dependents = 1, for example. (I know simple defaults can be set by the database schema, but more complex initializations must be executed by code.)
The custom initialization code must be preserved when the database schema is altered and EF regenerates the model code.
EF doesn’t provide a way to set properties each time an entity object is constructed in the database-first scenario. Editing the EF-generated code doesn’t work because it gets overwritten whenever EF regenerates the code after a change to the database schema. So far, four workarounds come to mind:
One idea is to add a constructor with more than the default zero-parameter constructor for each entity class. For example, c = new Customer(x) rather than the default c = new Customer(). Application code would call the new constructor, which would inherit the default constructor and add additional code to initialize the class properties. This avoids duplicating the default constructor, something that isn’t permitted by C#. The new constructor is in a separate partial class file, so it will not be overwritten when EF generates updated models from the database.
However, there is a risk that the application programmer may call the default constructor by accident, leading to subtle bugs.
Another solution is to wrap the entity classes in another class, say, a Customer2 class wrapped around the Customer class. The new class would inherit the original class and add initialization code for any properties as needed.
Since these new classes are separate from the original entity class code, they will not be overwritten by EF when it regenerates model code. It may be possible to hide the entity classes from the top-level application code, to avoid accidentally referring to the original classes by accident. If so, this should be a good technique, although I haven’t tested it yet.
A third-party tool, EntityFramework Reverse POCO Generator, is a help. It generates POCO model code much as EF does, but it is not EF. It has an option to generate partial classes, and the entity classes include a InitializePartial() method much like Linq2Sql’s OnCreated(). I think this will work fine for regenerating code as the database is altered over time. My concern here is that this is a third-party product, and there’s always a risk that it can become obsolete or unsupported.
Finally, you can alter the template that EF uses to generate code. The basic idea is to have the generated code add “partial void OnCreated()” to each class, and this lets us use the same convenient technique built into Linq2Sql. I assume newer versions of EF may overwrite the template changes, but it’s just one change in the template rather than changes to every entity class. This method is described here (How to efficiently set default entity values in Entity Framework 6, Database First) and the YouTube video is here (https://www.youtube.com/watch?v=i8J2ipImMuU).
Thanks to all who contributed! I hope this page is helpful to others, so you don’t have to burn as much time as I did looking for a solution.
Use the EF Reverse poco template- it will derive defaults from the database. You can override the InitializePartial method in your partial class to set defaults in code.
Coming from the EF background, I generally do it in the code first migration manually. In the up function of the generated migration, you can do something like this
AddColumn("dbo.Person", "IsActive", c => c.Boolean(nullable: false, defaultValue: true));
AddColumn("dbo.Person", "Name", c => c.String(nullable: false, defaultValue: "Mirza"));
Or to add default SQL value, use
AddColumn("dbo.Person", "CreatedDate",
c => c.String(nullable: false, defaultValueSql: "GETDATE()"));
However there's a downside of this approach in my opinion which is you have to keep a track of your (useless) migrations.
Just found this post looking for an answer to the same issue. Here's a work around that works for me.
Create a partial class for the entity (DB Table) you want to specify default values for, eg:
namespace myApplication.MyModel
{
public partial class myEntityName
{
public myEntityName(bool InitialiseOnConstruct) : this()
{
if (InitialiseOnConstruct)
{
this.property1 = defaultValue1;
this.property2 = defaultValue1;
}
}
}
}
Then in the code, to construct the entity:
thisEntity = new EntityName(true);
OK, it's an extra step, but it works. Hope that helps.

How to efficiently set default entity values in Entity Framework 6, Database First

I am new to Entity Framework and have only worked with database first development so far. I have been reading Entity Framework 2E which focuses on EF4. The generated classes in EF4 had no parameterless constructor so I was able to define partial classes and initialize entity properties in the parameterless constructors I defined there. The other options were to edit the EDMX directly and set the StoreGeneratedPattern attribute of a property to Computed or set the Default Value attribute of the property. The problem with the latter 2 options is that they'd be wiped out whenever I'd Update From Model. The parameterless constructors in partial classes worked nicely and were never wiped out.
Now in EF6, the partial classes look like POCOs and are not tightly coupled to EntityObject. However, they define parameterless constructors. Is there a way to set default values or initialize object properties on creation that won't get wiped out when I update the model?
I know I can resort to event handlers like Inserting on a data source, but I'd like to just set it globally.
Thanks
Okay I found the solution. Edit the template to input a partial method definition and a call to it in the constructor, then implement the partial method in a partial class.
Full explanation found here: https://www.youtube.com/watch?v=i8J2ipImMuU

Regenerating an entity using EF 6.1 DataBase First without losing Enum Type

I'm having a difficult time trying to understand:
1) How to add an Enum Type to an Entity
2) How to convert an existing property type in an Entity to an Enum.
I've read several docs, tried some things but none seem clear...
I went to the Model Browser to add a new Enum type and added this field to my entity. First off, is this the correct way of doing it? Secondly, if I regenerate the entity, I will lose my Enum type. Can this be prevented?
Secondly, how can I convert an existing property in an entity to an Enum type?
I like doing DataBase First, because when using WCF, I can edit the edmx template for attributes needed for namespaces and WCF specific items.
I can use a buddy class for the data validation against my ViewModels as opposed to Code First where it automatically creates the assumed DataAnnotations.
Any help would be appreciated.
1) With database first you cannot do this, only code first. Most people use a T4 script to create an Enum class based on these lookup tables.
2) Can't, again, code first only.

Customize entity materialization in Entity Framework 6

Is there a way to materialize an instance of your own class that derives from the entity type specified in your model? Let's say I have a "ClassName" property in my model for a given entity and whenever EF materializes an instance of the entity, I want to create an instance of the specified ClassName instead (which is a sub-class of the entity of course).
I know there is the ObjectMaterialized event on the ObjectContext but at this point the entity is already created.
var objectContext = ((IObjectContextAdapter)dbContext).ObjectContext;
objectContext.ObjectMaterialized += OnObjectMaterialized;
I need a hook right before this to customize the object creation. You might ask why on earth would I need to do this. I have a large object model that changes constantly so I can't define all my classes in the EDMX. The properties that I store in the database can be abstracted to a couple classes at the top of the object model hierarchy. I intend to create entities for those using table-per-type inheritance. But if I could retrieve specific object instances directly when using EF that would be awesome.
Thanks!
I wanted to create custom proxys and debugged deep into the entity framework. I found the translator class, which is responsible to create the entities by reflection. The namespace of the class is System.Data.Entity.Core.Common.Internal.Materialization.
The method creating the entites is the private method Emit_ConstructEntity. The entity type is a parameter and is created by the private method LookupObjectMapping based on an EdmType object (I was using model first).
If you want to change the class, which are created, you have to create a custom MetaDataWorkspace. The workspace is responsible to select the EdmType. Maybe try to debug into the methods yourself and have a look how the MetaDataWorkspace is used to identify the CLR type.

Entity Framework Database first How to alter entities to make them derive from a base class

I have a database already full of tables with data in them. What I have seen is that all tables have 5 columns in common:
Id-long, key
IsDeleted, bit
DateDeleted, SmallDatetime
LastUpdated, SmallDatetime
LastUpdatedUser, nvarchar
Now, there are some common operations that are done based on those fields which currently are replicated everywhere
What I want is to create a base class containing just these common attributes and the methods done to them and make every other entity derive from this.
I don't need or want to have this base entity on the database per se, this is just something I want to help the coding part.
The issue is this is Database first, I cannot alter the database so all I have to work with are the POCO classes and the EDMX.
How can i achieve this?
What you are looking for is something similar to TPH (http://msdn.microsoft.com/en-us/data/jj618292.aspx)
I don't think this will work for you however, as you have multiple existing tables.
One of the possible solutions is:
Create a base class called "BaseModel" (or something like that)
Add those properties as abstracts to force them to be overridden
Create a method in that base class to populate those fields, or create a helper which takes BaseModel, IsDeleted,LastUpdated, LastUpdatedUser as a parameter and update the model.
Extend the partial classes generated by the model.tt file and inherit from the BaseModel class.
Thanks,
Dave
Expand the .edmx file and open the Model.tt file (not the Model.Context.tt one)
Find the row where the definition of the "partial class" is being
announced.
Should look something like that:
<#=codeStringGenerator.EntityClassOpening(entity)#>
Add the inheritance " : YourBaseClass" to the end of the row
Done. Once you save the model you will have all your old entities deriving the base class and when a new one is generated by this template it will derive the base class as well.

Categories