Reputation: 261
I have generated my EDMX from an existing database which contains default column values. I have also POCO object generated with T4 template.
Now I have a scenario where I want to create a POCO and save it to the database like this:
dim tablePocoEntityInstance as New tablePocoEntity
context.MsSQLTable.AddObject(tablePocoEntityInstance)
context.SaveChanges()
This is working fine with exception of default values that are set in the SQL Server database.
For example:
SQL Server Table
id (int, not null, auto increament)
magicNR (int, not null, defaultValue = 11)
Generated POCO object has then two properties:
Partial Public Class tablePocoEntity
Public Overridable Property id As Integer
Public Overridable Property magicNR As Integer
...
Problem is that magicNR
is not nullable and get implicitly initialized. When I save the object, id
is as it should be but magicNR
has value 0 and not 11 which is the default value.
My questions:
Upvotes: 2
Views: 1356
Reputation: 2169
Ok, this question is quite old but still I'd like to share my solution to this.
What I did is to modify the T4 template in order to add a partial method to all generated entities and to call it from the constructor. This partial method is implemented in an extended partial class which you will manually create for each entity you need to set default values.
Note: I'm using EF6
Short steps:
1) Modify the T4 template to include a partial method like this:
partial void OnCreationComplete();
2) Modify the T4 template to invoke that method in the constructor
OnCreationComplete();
3) Create a partial class for those entities which you need to set a default property and implement the OnCreationComplete method:
partial void OnCreationComplete()
{
PropertyFoo = "Bar";
}
Here is the complete code:
T4 Template
// You might want to remove the IF statement that excludes the constructor generation for entities without collection and complex entities...
<#
var propertiesWithDefaultValues = typeMapper.GetPropertiesWithDefaultValues(entity);
var collectionNavigationProperties = typeMapper.GetCollectionNavigationProperties(entity);
var complexProperties = typeMapper.GetComplexProperties(entity);
#>
public <#=code.Escape(entity)#>()
{
<#
foreach (var edmProperty in propertiesWithDefaultValues)
{
#>
<#=code.Escape(edmProperty)#> = <#=typeMapper.CreateLiteral(edmProperty.DefaultValue)#>;
<#
}
foreach (var navigationProperty in collectionNavigationProperties)
{
#>
<#=code.Escape(navigationProperty)#> = new HashSet<<#=typeMapper.GetTypeName(navigationProperty.ToEndMember.GetEntityType())#>>();
<#
}
foreach (var complexProperty in complexProperties)
{
#>
<#=code.Escape(complexProperty)#> = new <#=typeMapper.GetTypeName(complexProperty.TypeUsage)#>();
<#
}
#>
OnCreationComplete();
}
partial void OnCreationComplete();
Example of generated class:
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace MyTest.DAL
{
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
public partial class Foo
{
public Foo()
{
OnCreationComplete();
}
partial void OnCreationComplete();
public string MyPropertyFoo { get; set; }
}
}
Extended partial class
public partial class Foo
{
partial void OnCreationComplete()
{
MyPropertyFoo = "Bar";
}
}
Hope it helps someone...
Upvotes: 0
Reputation: 719
Open up your entity .edmx and right click on the data field in question and select properties. Under DataBaseScriptGeneration, change StoreGeneratedPattern to "Computed". Once that it set, your app will work as expected - where SQL Server inserts the default value. However, you will then not be able to force a value from the app side.
Upvotes: 2
Reputation: 755401
There is no out-of-the-box solution that I'd be aware of - but since those POCO classes are generated from the database using T4 templates, you could always modify those templates to inspect the database and find and honor column defaults.
In that case, your object then might have a constructor that would set those columns to the default values that the database definition defines.
Upvotes: 1