Reputation: 1255
I'm using EF 6.0 and want to add custom logic into/after default constructor execution of any class generated by Model.edmx file. Found that in deprecated EntityObject generator version there was partial void OnCreated method in each generated class that may be overwritten in partial class to achieve what I want, but can't find any topics and can't figure out how to do this without deprecated approach usage. For example, I have generate collection of next items:
public virtual DbSet<AnswerOption> AnswerOptions { get; set; }
My custom generated class is AnswerOption
and I need customize it's default constructor that was generated in Model.cs file:
public partial class AnswerOption
{
public AnswerOption()
{}
}
or at least execute some code after default constructor invocation defined in my partial class
Upvotes: 2
Views: 3238
Reputation: 2165
Your solution is good, but I thought I would add a slight variation for others that opens up lots of useful functionality.
Edit your tt file to make the Context use your own Base class e.g
<#=Accessibility.ForType(container)#> partial class <#=code.Escape(container)#> : DataContextBase {
public <#=code.Escape(container)#>()
: base("name=<#=container.Name#>")
{
Then create your base class with all the built in common functions you use. I have hundreds of useful functions, like events on saving, undoing changes, getting information about entities etc. You can then add a call to your base virtual OnCreated in the constructor like below
/// <summary>
/// A base EntityFramework DataContext class
/// </summary>
public partial class DataContextBase : DbContext, IDataContext
{
/// <summary>
/// Provides asynchronous locking capabilities
/// </summary>
protected readonly AsyncLock _databaseLock = new AsyncLock("DataContext");
public event EventHandler Disposed;
public event SavedChangesEventHandler SavedChanges;
public event EntitiesChangedEventHandler EntitiesChanged;
/// <summary>
/// A dictionary containing all EntityFramework types and properties
/// </summary>
private readonly Dictionary<string, List<string>> EntityFrameworkPropertyCache;
private ILoggingService _log;
private IExceptionService _exception;
private IEnumerable<object> _deletedEntities;
private Dictionary<string, string> _schemaCache;
/// <summary>
/// A lock that can be awaited for co-ordinating (serialising) access to the DataContext
/// </summary>
public AsyncLock DatabaseLock { get { return _databaseLock; } }
/// <summary>
/// Gets a reference to the underlying ObjectContext
/// </summary>
public ObjectContext Context { get { return ((IObjectContextAdapter)this).ObjectContext; } }
/// <summary>
/// Gets or sets the Command Timeout
/// </summary>
public int? CommandTimeout
{
get { return Database.CommandTimeout; }
set
{
Database.CommandTimeout = value;
Context.CommandTimeout = value;
}
}
/// <summary>
/// Gets the underlying SqlConnection
/// </summary>
public SqlConnection SqlConnection { get { return (SqlConnection) ((EntityConnection) Context.Connection).StoreConnection; } }
/// <summary>
/// Checks whether we can connect
/// </summary>
public bool CanConnect { get { return Database.Exists(); } }
/// <summary>
/// Gets the Server this DataSource this instance is connected to
/// </summary>
public string DataSource { get { return Database.Connection.DataSource; } }
/// <summary>
/// Gets or sets whether the context Lazyily loads properties on access
/// </summary>
public bool LazyLoadingEnabled
{
get { return Configuration.LazyLoadingEnabled; }
set { Configuration.LazyLoadingEnabled = value; }
}
/// <summary>
/// Gets or sets whether AutoDetechChanges is Enabled
/// </summary>
public bool AutoDetectChangesEnabled
{
get { return Configuration.AutoDetectChangesEnabled; }
set { Configuration.AutoDetectChangesEnabled = value; }
}
/// <summary>
/// Gets or sets whether ValidateOnSave is Enabled
/// </summary>
public bool ValidateOnSaveEnabled
{
get { return Configuration.ValidateOnSaveEnabled; }
set { Configuration.ValidateOnSaveEnabled = value; }
}
/// <summary>
/// Gets whether this DataContext is disposed
/// </summary>
public bool IsDisposed { get; private set; }
/// <summary>
/// Gets or sets whether DataContext events are raised
/// </summary>
public bool NotificationsBlocked { get; set; }
/// <summary>
/// Gets all Entities that are Modified
/// </summary>
public List<object> ModifiedEntities
{
get { return GetObjectStateEntries(EntityState.Modified).Select(e => e.Entity).ToList(); }
}
/// <summary>
/// Gets all Entities that are Modified
/// </summary>
public List<object> AddedEntities
{
get { return GetObjectStateEntries(EntityState.Added).Select(e => e.Entity).ToList(); }
}
/// <summary>
/// Gets all Entities that are Modified
/// </summary>
public List<object> DeletedEntities
{
get { return GetObjectStateEntries(EntityState.Deleted).Select(e => e.Entity).ToList(); }
}
/*
* Instantiation
*/
/// <summary>
/// Constructs a new DataContextBase
/// </summary>
public DataContextBase ()
{
EntityFrameworkPropertyCache = Context.GetEntityPropertDictionary();
SavedChanges += OnSavedChanges;
AddLocalEntityChangedEventHandler();
OnCreated();
}
/// <summary>
/// Constructs a new DataContextBase for the specified configuration connection key
/// </summary>
/// <param name="connectionKey">The config connection key</param>
public DataContextBase (string connectionKey)
: base(connectionKey)
{
EntityFrameworkPropertyCache = Context.GetEntityPropertDictionary();
SavedChanges += OnSavedChanges;
AddLocalEntityChangedEventHandler();
OnCreated();
}
protected virtual void OnCreated()
{
}
}
Upvotes: 1
Reputation: 1255
Ended up by editing Model.tt T4 template file. Removed default condition for parameterless constructor generation(for my case it were 34,35,64 lines):
if (propertiesWithDefaultValues.Any() || collectionNavigationProperties.Any() || complexProperties.Any())
{
}
Added
partial void OnConstructorConpletion();
generation for each entity class with it's call in the end of parameterless constructor:
#>
public <#=code.Escape(entity)#>()
{
<#
//default T4 logic that was processing properties
#>
OnConstructorConpletion();
}
partial void OnConstructorConpletion();
<#
So, the result generated code for class from question sample by T4 template was:
public partial class AnswerOption
{
public AnswerOption()
{
OnConstructorConpletion();
}
}
Upvotes: 1
Reputation: 678
DbContext has OnModelCreating, which can be used after initial DbContext, but before the DbContext is locked down:
DbSet does not have the equivalent, but you can create Partial class implementations on the model classes created, which are derived from DbSet and embed your unique logic in those. These should be in separate files from the ones created by Entity Framework so that if you recreate the entity classes your code doesn't get replaced.
Upvotes: 0