none
Mapping simple audit audit columns in entity framework 6 (code first) RRS feed

  • Question

  • Some of the entities in my application have 4 audit properties on them:

    public virtual DateTime WhenAdded { get; set; }
    public virtual DateTime? WhenUpdated { get; set; }
    public virtual User AddedBy { get; set; }
    public virtual User UpdatedBy { get; set; }

    I am using a code first approach and have the following extension method to map the user properties:

    public static void MapAuditFields<T>(this EntityTypeConfiguration<T> configuration)
        where T : class, IAuditable
    {
        configuration.HasOptional<User>(e => e.AddedBy)
            .WithOptionalDependent()
            .Map(a => a.MapKey("AddedByUserId"));
        configuration.HasOptional<User>(e => e.UpdatedBy)
            .WithOptionalDependent()
            .Map(a => a.MapKey("UpdatedByUserId"));
    }

    2 example entity mappings are:

    public class AddressConfiguration : EntityTypeConfiguration<Address>
    {
        public AddressConfiguration()
        {
           this.HasKey(x => x.Id);
           this.Property(x => x.Id).HasColumnNam("AddressId");
           this.MapAuditFields();
        }
    }
    
    public class TestConfiguration : EntityTypeConfiguration<Test>
    {
        public TestConfiguration()
        {
            this.HasKey(x => x.Id);
            this.Property(x => x.Id).HasColumnName("TestId");
            this.MapAuditFields();           
        }
    }

    This is working fine when I only map one entity with these properties, but as soon as I add a second I get an error "Sequence contains more than one matching element". Is this a bug in entity framework or am I doing something wrong?

    Thursday, February 20, 2014 9:16 AM

Answers

  • Hello,

    Could you please share how do you define these entities clasees? Because I made a test which is similar with yours, however, it could create the database successfully. My demo codes:

    using System;
    
    using System.Collections.Generic;
    
    using System.ComponentModel.DataAnnotations.Schema;
    
    using System.Data.Entity;
    
    using System.Linq;
    
    using System.Text;
    
    using System.Threading.Tasks;
    
    
    namespace P201401CF.S0220
    
    {
    
        public class S0220Context : DbContext
    
        {
    
            public DbSet<User> Users { get; set; }
    
    
            public DbSet<Address> Addresses { get; set; }
    
    
            public DbSet<Test> Tests { get; set; }
    
    
            protected override void OnModelCreating(DbModelBuilder modelBuilder)
    
            {
    
                modelBuilder.Entity<User>().HasKey(u => u.UserID).Property(u => u.UserID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
    
    
                modelBuilder.Entity<Address>().HasKey(a => a.AddressID).Property(a => a.AddressID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
    
    
                modelBuilder.Entity<Test>().HasKey(a => a.TestID).Property(a => a.TestID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
    
    
                modelBuilder.Entity<Address>().HasOptional(a => a.AddedBy).WithOptionalDependent().Map(a => a.MapKey("AddedByUserID"));
    
    
                modelBuilder.Entity<Address>().HasOptional(a => a.UpdatedBy).WithOptionalDependent().Map(a => a.MapKey("UpdatedByUserID"));
    
    
                modelBuilder.Entity<Test>().HasOptional(a => a.AddedBy).WithOptionalDependent().Map(a => a.MapKey("AddedByUserID"));
    
    
                modelBuilder.Entity<Test>().HasOptional(a => a.UpdatedBy).WithOptionalDependent().Map(a => a.MapKey("UpdatedByUserID"));
    
            }
    
    
        }
    
    
        public class User
    
        {
    
            public int UserID { get; set; }
    
    
            public string UserName { get; set; }
    
        }
    
    
        public class Address
    
        {
    
            public int AddressID { get; set; }
    
    
            public string AddressName { get; set; }
    
    
            public DateTime WhenAdded { get; set; }
    
    
            public DateTime WhenUpdated { get; set; }
    
    
            public virtual User AddedBy { get; set; }
    
    
            public virtual User UpdatedBy { get; set; }
    
        }
    
    
        public class Test
    
        {
    
            public int TestID { get; set; }
    
    
            public string TestName { get; set; }
    
    
            public DateTime WhenAdded { get; set; }
    
    
            public DateTime WhenUpdated { get; set; }
    
    
            public virtual User AddedBy { get; set; }
    
    
            public virtual User UpdatedBy { get; set; }
    
        }
    
    }
    

    The created tables:

    You can have a try with my demo codes.

    If this does not work for you, please let me know.

    Regards.


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Friday, February 21, 2014 5:13 AM
    Moderator