2

Currently I have created a Base Entity type that all my entities will derive from.

public abstract class BaseEntity
    {

        /// <summary>
        /// Key Field for all entities
        /// </summary>
        /// 
        [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public Guid Id { get; set; }


        /// <summary>
        /// Date entity was created
        /// </summary>
        public DateTime DateCreated { get; set; }

        /// <summary>
        /// Last date Modified
        /// </summary>
        public DateTime DateModified { get; set; }

        /// <summary>
        /// keep track of Row Version used for concurrency
        /// </summary>
        [Timestamp]
        public Byte[] RowVersion { get; set; }

    }
}

I am thinking of decoupling my model from entity framework so it is not reliant on it. I’d like to have another project that is for my EF implementation. So, I would like to include the mappings in that project that will make up the relationships in my model.

Since my BaseEntity class is an abstract class what is the best way for me to keep my [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] and [TimeStamp] attributes so that it will apply to all my derived entities using the fluent API and separate mapping file? I don't think I can setup the modeler to add the BaseEntity mapping becasue it is an abstract class. Should I create an interface that has all my base functionality and repeat the mappings for all my entities?

I am using the EntityTypeConfiguration class and creating separate mapping classes for all my entities.

DDiVita
  • 4,225
  • 5
  • 63
  • 117
  • I prefer interfaces. Keeps the coupling a little looser and doesn't piss off Entity Framework about having base classes that aren't mapped to the schema. – Jeff Jul 11 '11 at 20:24
  • Duplicate: https://stackoverflow.com/q/15578528/861716 – Gert Arnold Nov 15 '20 at 14:35

2 Answers2

8

You can use base class:

public abstract class BaseEntity
{
    public Guid Id { get; set; }
    public DateTime DateCreated { get; set; }
    public DateTime DateModified { get; set; }
    public Byte[] RowVersion { get; set; }
}

Now it depends if you want to have inheritance mapped or not. I guess you don't want so define your configuration like:

public class BaseEntityConfiguration<TEntity> : EntityTypeConfiguration<TEntity>
    where TEntity : BaseEntity
{
    public BaseEntityConfiguration()
    {
        HasKey(e => e.Id);
        // This is not very good - check http://stackoverflow.com/questions/6098972/guid-comb-strategy-in-ef4-1-codefirst/6100606#6100606
        Property(e => e.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
        Property(e => RowVersion).IsRowVersion();
    }
}    

Now for each entity derived from BaseEntity derive its configuration from BaseEntityConfiguration,

Ladislav Mrnka
  • 360,892
  • 59
  • 660
  • 670
  • @Ladislav: Does this `BaseEntityConfiguration` really work for any type other than `BaseEntity` itself? I just had this (http://stackoverflow.com/questions/7177508/multiple-inheritance-issue-with-ef-4-1/7178165#7178165) frustrating discussion with DDiVita where he says "it works" and I on the other side was sure that it doesn't because I believe that it's the source of the exception in his question: *"The property 'Id' is not a declared property on type..."*. (I've made this little example in my answer in hope it's a prove.) But reading your answer here I'm getting unsure now. – Slauma Aug 25 '11 at 21:13
  • 1
    @Slauma: It works but the only reason why it works is that `BaseEntity` is not an entity - it is just a class. You cannot create `DbSet`. This is not TPC inheritance, this is for POCO entity with shared parent class which is not an entity. If `BaseEntity` will be entity as well you will indeed get that error. – Ladislav Mrnka Aug 25 '11 at 22:25
  • Aaaaaah, now I see the difference! I even wasn't aware that I could have a non-entity base class. Now, it's a great answer, +1, lol :) – Slauma Aug 25 '11 at 22:45
  • @Slauma: That is the main point for POCO to have possibility to define custom base class. – Ladislav Mrnka Aug 25 '11 at 22:46
0

It is not a good practice for classes to inherit a base.

It is better to prioritize composition and deprioritize inheritance for these cases.

Therefore, you should include as one more attribute of each entity a class that represents the metadata with the attributes of the BaseEntity class.

GL

Source

Braian Coronel
  • 22,105
  • 4
  • 57
  • 62
  • You don't seem to understand why a base class *or* interface (and nothing else) is required here. – Gert Arnold Nov 15 '20 at 14:38
  • The solution strategy must be approached by composition because inheritance is not a good practice. Instead of entities inheriting from base, they should compose to base with a class member. If necessary I attach an example. – Braian Coronel Nov 15 '20 at 22:30
  • In DDD you're (arguably) right. The only thing OP is after is to have db tables with IDs and auditing fields. – Gert Arnold Nov 16 '20 at 07:45