Entity Framework 6.0 entity custom constructor logic implementation

c# entity-framework-6

Question

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

1
2
8/3/2015 7:29:37 PM

Accepted Answer

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();
    }
}
1
8/7/2015 12:19:09 PM

Popular Answer

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()
        {
        }
}


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow