简体   繁体   中英

EF Code First Configuration of shared Base Class --> Single Configuration File

I am using EF 5.0 Code First in a C# project. I have a base clase which the majority of my domain models derive from.

public abstract class AuditableModelBase
{
    public Int32 CreatedByUserId { get; set; }

    public DateTime CreatedDate { get; set; }

    public virtual UserProfile CreatedByUserProfile { get; set; }

    public Int32 UpdatedByUserId { get; set; }

    public DateTime UpdatedDate { get; set; }

    public virtual UserProfile UpdatedByUserProfile { get; set; }

    public AuditableModelBase()
    {
        CreatedByUserId = 1;
        CreatedDate = DateTime.UtcNow;
        UpdatedByUserId = 1;
        UpdatedDate = DateTime.UtcNow;
    }
}

However, for every single entity I have to define the specific configurations to wire these relationships together.

// Relationships
        this.HasRequired(amb => amb.CreatedByUserProfile).WithMany().HasForeignKey(amb => amb.CreatedByUserId).WillCascadeOnDelete(false);
        this.HasRequired(amb => amb.UpdatedByUserProfile).WithMany().HasForeignKey(amb => amb.UpdatedByUserId).WillCascadeOnDelete(false);

I'm looking for a way to just declare one Configuration similar to the one directly above for the abstract base class instead of having to create an individual configuration file for each of my entities. I'd love to just have one file named "AuditableModelBaseMap.cs" which will have my configuration instead of "Entity1Map.cs", "Entity2Map.cs", "Entity3Map.cs", etc. especially since all of those files have the exact same code inside.

Any advice?

Thanks.

Try it like below but I didnt test it .However if I were you, I wouldnt design Audit tables this way

class AuditableModelBaseMap : EntityTypeConfiguration<AuditableModelBase>
    {
        public AuditableModelBaseMap ()
        {
            this.HasRequired(amb => amb.CreatedByUserProfile).WithMany().HasForeignKey(amb => amb.CreatedByUserId).WillCascadeOnDelete(false);
            this.HasRequired(amb => amb.UpdatedByUserProfile).WithMany().HasForeignKey(amb => amb.UpdatedByUserId).WillCascadeOnDelete(false);
        }
    }

THIS IS MY WAY OF Doing AUDITING

        public interface IEntity
            {
                int Id { get; set; }
            }

         public interface IAuditable : IEntity
            {
                string UpdatedBy { get; set; }
                string CreatedBy { get; set; }
                DateTime CreatedDate { get; set; }
                DateTime UpdateDate { get; set; }
            }

    Now any entity which is auditable will implement this class your context will look the following




            public class MYContext : DbContext, ILicensingContext
            {
                private readonly IAuditLogBuilder _auditLogBuilder;


                public LicensingContext()
                    : this(new AuditLogBuilder())
                {
                }
                private IDbSet<Device> Devices { get; set; }

                private IDbSet<AuditLog> AuditLogs { get; set; }


                public MyContext(IAuditLogBuilder auditLogBuilder)
                {
                    _auditLogBuilder = auditLogBuilder;
                }



                /// <summary>
                ///     1. Constructs the AuditLog objects from the context
                ///     2. Calls SaveChanges to save the actual object modified
                ///     3. It updates the Log objects constructed in step 1 to populate the IDs returned from the Db
                ///     4. Saves the AuditLogs
                /// </summary>
                /// <returns></returns>
                public override int SaveChanges()
                {
                    var entries = ChangeTracker.Entries<IAuditable>().ToList();

                    _auditLogBuilder.UpdateAuditables(entries);
                    IEnumerable<AuditLog> auditLogEntities = _auditLogBuilder.ConstructAuditLogs(entries).ToList();


                    int countOfAffectedRecords = base.SaveChanges();

                    _auditLogBuilder.UpdateAuditLogs(auditLogEntities);
                    foreach (AuditLog auditLogEntity in auditLogEntities)
                    {
                        GetDbSet<AuditLog>().Add(auditLogEntity);
                    }
                    base.SaveChanges();
                    return countOfAffectedRecords;
                }


                public IDbSet<TEntity> GetDbSet<TEntity>() where TEntity : class
                {
                    return Set<TEntity>();
                }
            }

 public class AuditLogBuilder : IAuditLogBuilder
    {
        private string _username;

        private string Username
        {
            get
            {
                if (HttpContext.Current != null && HttpContext.Current.User != null)
                {
                    _username = HttpContext.Current.User.Identity.Name;
                }

                if (String.IsNullOrWhiteSpace(_username))
                {
                    _username = "Service Consumer";
                }
                return _username;
            }
        }

        public IEnumerable<AuditLog> ConstructAuditLogs(IEnumerable<DbEntityEntry<IAuditable>> auditableEntities)
        {
            var audits = new List<AuditLog>();
            if (auditableEntities != null)
            {
                audits.AddRange(auditableEntities
                                .Where(
                                     e =>
                                     e.State == EntityState.Modified || e.State == EntityState.Added ||
                                    e.State == EntityState.Deleted)
                           .SelectMany(GetAuditLogs));
            }
            return audits;
        }

        public void UpdateAuditLogs(IEnumerable<AuditLog> auditLogEntities)
        {
            foreach (AuditLog auditLog in auditLogEntities)
            {
                auditLog.RecordId = auditLog.Entity.Id;
                auditLog.UpdatedBy = auditLog.Entity.UpdatedBy;

                if (String.Equals(auditLog.PropertyName, "id", StringComparison.CurrentCultureIgnoreCase))
                {
                    auditLog.NewValue = auditLog.Entity.Id.ToString(CultureInfo.CurrentCulture);
                }
            }
        }

        public void UpdateAuditables(IEnumerable<DbEntityEntry<IAuditable>> entries)
        {
            if (entries != null)
            {
                foreach (var entry in entries)
                {
                    entry.Entity.UpdateDate = DateTime.UtcNow;
                    entry.Entity.UpdatedBy = Username;
                    if (entry.Entity.Id == 0)
                    {
                        entry.Entity.CreatedDate = DateTime.UtcNow;
                        entry.Entity.CreatedBy = Username;
                    }
                }
            }
        }

        private static IEnumerable<AuditLog> GetAuditLogs(DbEntityEntry<IAuditable> entry)
        {
            var audits = new List<AuditLog>();

            string entityName = ObjectContext.GetObjectType(entry.Entity.GetType()).Name;

            switch (entry.State)
            {
                case EntityState.Added:

                    audits.AddRange(entry.CurrentValues.PropertyNames.Select(propertyName =>
                                                                             new AuditLog
                                                                                 {
                                                                                     EntityName = entityName,
                                                                                     CreateDate = DateTime.UtcNow,
                                                                                     NewValue =
                                                                                         entry.CurrentValues[
                                                                                             propertyName] != null
                                                                                             ? entry.CurrentValues[
                                                                                                 propertyName].ToString()
                                                                                             : String.Empty,
                                                                                     PreviousValue = String.Empty,
                                                                                     PropertyName = propertyName,
                                                                                     Entity = entry.Entity,
                                                                                     Action = Actions.Create.ToString()
                                                                                 }));
                    break;

                case EntityState.Deleted:
                    audits.AddRange(entry.OriginalValues.PropertyNames.Select(propertyName =>
                                                                              new AuditLog
                                                                                  {
                                                                                      EntityName = entityName,
                                                                                      CreateDate = DateTime.UtcNow,
                                                                                      NewValue = String.Empty,
                                                                                      PreviousValue =
                                                                                          entry.OriginalValues[
                                                                                              propertyName] != null
                                                                                              ? entry.OriginalValues[
                                                                                                  propertyName].ToString
                                                                                                    ()
                                                                                              : String.Empty,
                                                                                      PropertyName = propertyName,
                                                                                      Entity = entry.Entity,
                                                                                      Action = Actions.Delete.ToString()
                                                                                  }));

                    break;

                case EntityState.Modified:

                    audits.AddRange(entry.OriginalValues.PropertyNames.
                                          Where(
                                              propertyName =>
                                              !Equals(entry.OriginalValues[propertyName],
                                                      entry.CurrentValues[propertyName]))
                                         .Select(propertyName =>
                                                 new AuditLog
                                                     {
                                                         EntityName = entityName,
                                                         CreateDate = DateTime.UtcNow,
                                                         NewValue =
                                                             entry.CurrentValues[propertyName] != null
                                                                 ? entry.CurrentValues[propertyName].ToString()
                                                                 : String.Empty,
                                                         PreviousValue =
                                                             entry.OriginalValues[propertyName] != null
                                                                 ? entry.OriginalValues[propertyName].ToString()
                                                                 : String.Empty,
                                                         PropertyName = propertyName,
                                                         Entity = entry.Entity,
                                                         Action = Actions.Update.ToString()
                                                     }));
                    break;
            }
            return audits;
        }
    }

Have you tried this?

public class AuditableModelBaseMap : EntityTypeConfiguration<AuditableModelBase>
{
    public AuditableModelBaseMap()
    {
        this.HasRequired(amb => amb.CreatedByUserProfile).WithMany().HasForeignKey(amb => amb.CreatedByUserId).WillCascadeOnDelete(false);
        this.HasRequired(amb => amb.UpdatedByUserProfile).WithMany().HasForeignKey(amb => amb.UpdatedByUserId).WillCascadeOnDelete(false);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM