MapInheritedProperties()不映射继承的外键属性

时间:2012-09-14 14:18:28

标签: .net entity-framework entity-framework-5

这是我的实体类:

public abstract class Entity: IEntity
{
    public Guid? Id { get; set; }    
    public bool IsDead { get; set; }
    public DateTime Created { get; set; }
    public DateTime Modified { get; set; }
    public ICollection<EntityAccess> AccessList { get; set; }
    public ICollection<Message> Discussion { get; set; }
    public User Owner { get; set; }
}

我的大多数实体(包括用户)都继承自此类。 OnModelCreating,他们都通过这段代码:

m.MapInheritedProperties();
m.ToTable(entity.Name); };

EF创建数据库后,会发生一些非常奇怪的事情。从Entity继承的属性确实映射到每个表,除Owner属性。与其他继承的属性不同,未映射所有者。什么可以解释这个?

附加信息:我的实体是简单的POCO对象,没有注释,没有构造函数,没有任何东西。例如,这是用户实体:

public class User : RuntimeEntity
{
    public string Email { get; set; }
    public ICollection<UserGroup> Groups { get; set; }
    public byte[] Password { get; set; }
    public ICollection<Membership> Memberships { get; set; }
}

修改

由于这个问题仍然存在,这里是完整的模型:

namespace ConSol.Templex.Data.Entities
{
    public abstract class Association : IEntity
    {
        public Guid? Id { get; set; }
        [NotMapped]
        public virtual RuntimeEntity Entity1 { get; set; }
        [NotMapped]
        public virtual RuntimeEntity Entity2 { get; set; }
    }

public class Attachment : RuntimeEntity
    {
        public AttachmentValidity Validity { get; set; }
        public ICollection<Blob> Versions { get; set; }
        public Profile Profile { get; set; }

    #region Computed properties
        public string Name
        {   
            get 
            {
                    return this.Versions.Last().Name;
            }
        }
        #endregion
    }

public enum AttachmentValidity
    {
        Unverified,
        Verified,
        WorkInProgress
    }

public class Blob : RuntimeEntity
    {
        public string Name { get; set; }
        public byte[] Data { get; set; }
        public Attachment Attachment { get; set; }
        public WorkLog WorkLog { get; set; }
    }

public class EntityAccess : Association
    {
        #region Association implementation
        public override RuntimeEntity Entity1 { get { return this.Entity; } }
        public override RuntimeEntity Entity2
        {
            get
            {
                return this.UserGroup ?? this.User as RuntimeEntity;
            }
            set
            {
                if (value is User) this.User = (User)value; else this.UserGroup = (UserGroup)value;
            }
        }
        #endregion

    public RuntimeEntity Entity { get; set; }
        public UserGroup UserGroup { get; set; }
        public User User { get; set; }
    }
}
?
    public interface IEntity
    {
    }
}
?
    public abstract class MasterEntity : IEntity
    {
        public string Code { get; set; }
        public string Name { get; set; }
    }

public class Membership : Association
    {
        #region Association implementation
        public override RuntimeEntity Entity1 { get { return this.User; } }
        public override RuntimeEntity Entity2 { get { return this.UserGroup; } }
        #endregion

    public User User { get; set; }
        public UserGroup UserGroup { get; set; }
        public bool IsAdmin { get; set; }
    }

public class Message : RuntimeEntity
    {
        public string Text { get; set; }
        public RuntimeEntity RuntimeEntity { get; set; }

    #region Computed properties
        public User Author
        {
            get
            {
                return this.Owner;
            }
        }
        #endregion
    }

public class Parameter : RuntimeEntity
    {
        public string Code { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }

    public Worker Worker
        {
            get
            {
                throw new System.NotImplementedException();
            }
            set
            {
            }
        }
    }

public class ParameterValue : ConSol.Templex.Data.Entities.RuntimeEntity
    {
        public string Value { get; set; }
        public Parameter Parameter { get; set; }
        public Worker Worker { get; set; }

    public Profile Profile
        {
            get
            {
                throw new System.NotImplementedException();
            }
            set
            {
            }
        }
    }

public class ProductStatus : RuntimeEntity
    {
        public Profile Profile { get; set; }
        public Guid ProductId { get; set; }
        public ExportStatus Status { get; set; }
        public WorkLog WorkLog { get; set; }

    public enum ExportStatus
        {
            Exported,
            Imported,
            Error
        }
    }

public class Profile : RuntimeEntity
    {
        public string Name { get; set; }
        public ICollection<Attachment> Attachments { get; set; }
        public ICollection<ParameterValue> Parameters { get; set; }
        public ICollection<WorkLog> WorkLogs { get; set; }
        public Worker Exporter { get; set; }
        public Worker Importer { get; set; }
        public TimeSpan? Frequency { get; set; }
        public DateTime FirstRun { get; set; }
        public string Destination { get; set; }
        public ICollection<ProductStatus> ProductQueue { get; set; }
    }
}
?
    public abstract class RuntimeEntity : IEntity, ISoftDeletable
    {
        public Guid? Id { get; set; }

    public bool IsDead { get; set; }
        public DateTime Created { get; set; }
        public DateTime Modified { get; set; }
        //public ICollection<EntityAccess> AccessList { get; set; }
        public ICollection<Message> Discussion { get; set; }
        public User Owner { get; set; }

    /// <summary>
        /// This defines the default filter for all entities
        /// </summary>
        public static Expression<Func<TIn,bool>> DefaultFilterFor<TIn>(User user)
            where TIn : RuntimeEntity
        {
            return x => true;
        }

    /// <summary>
        /// This defines an optional filter to be used most of the time
        /// </summary>
        public static Expression<Func<TIn, bool>> AdditionalFilterFor<TIn>(User user)
            where TIn : RuntimeEntity
        {
            return x => !x.IsDead;
        }
    }

public class Schedule : RuntimeEntity
    {
        public DateTime Start { get; set; }
        public TimeSpan Frequency { get; set; }
    }

public class User : RuntimeEntity
    {
        public string Email { get; set; }
        public ICollection<UserGroup> Groups { get; set; }
        public byte[] Password { get; set; }
        public ICollection<Membership> Memberships { get; set; }
    }

public class UserGroup : RuntimeEntity
    {
        public string CustomerId { get; set; }
        public string Name { get; set; }
        public bool IsSuperGroup { get; set; }
        public ICollection<Membership> Memberships { get; set; }

    #region Computed properties
        public IEnumerable<User> Admins
        {
            get
            {
                return this.Memberships.Where(x => x.IsAdmin).Select(x => x.User);
            }
        }
        #endregion
    }

public class Worker : RuntimeEntity
    {
        public ICollection<Parameter> Parameters { get; set; }
        public string AssemblyName { get; set; }
        public byte[] Assembly { get; set; }
        public WorkType Work { get; set; }

    public enum WorkType
        {
            Import,
            Export
        }
    }

public class WorkerMessage : RuntimeEntity
    {
        public string Message { get; set; }
        public MessageType Outcome { get; set; }
        public WorkLog WorkLog { get; set; }

    public enum MessageType
        {
            Information,
            Warning,
            Error
        }
    }

public class WorkLog : RuntimeEntity
    {
        public DateTime End { get; set; }
        public Profile Profile { get; set; }
        public Worker Worker { get; set; }
        public WorkResult Result { get; set; }
        public ICollection<Blob> Files { get; set; }
        public ICollection<WorkerMessage> Report { get; set; }
    }

    public enum WorkResult
        {
            Success,
            Warning,
            Failure
        }
    }
}

这是dbcontext:

public class TemplexDB : DbContextBase
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Attachment>().Map(m =>
        {
            m.MapInheritedProperties();
            m.ToTable("Attachment");
        });
        modelBuilder.Entity<Blob>().Map(m =>
        {
            m.MapInheritedProperties();
            m.ToTable("Blob");
        });
        modelBuilder.Entity<Message>().Map(m =>
        {
            m.MapInheritedProperties();
            m.ToTable("Message");
        });
        modelBuilder.Entity<Parameter>().Map(m =>
        {
            m.MapInheritedProperties();
            m.ToTable("Parameter");
        });
        modelBuilder.Entity<ParameterValue>().Map(m =>
        {
            m.MapInheritedProperties();
            m.ToTable("ParameterValue");
        });
        modelBuilder.Entity<ProductStatus>().Map(m =>
        {
            m.MapInheritedProperties();
            m.ToTable("ProductStatus");
        });
        modelBuilder.Entity<Profile>().Map(m =>
        {
            m.MapInheritedProperties();
            m.ToTable("Profile");
        });
        modelBuilder.Entity<Schedule>().Map(m =>
        {
            m.MapInheritedProperties();
            m.ToTable("Schedule");
        });
        modelBuilder.Entity<User>().Map(m =>
        {
            m.MapInheritedProperties();
            m.ToTable("User");
        });
        modelBuilder.Entity<UserGroup>().Map(m =>
        {
            m.MapInheritedProperties();
            m.ToTable("UserGroup");
        });
        modelBuilder.Entity<Worker>().Map(m =>
        {
            m.MapInheritedProperties();
            m.ToTable("Worker");
        });
        modelBuilder.Entity<WorkerMessage>().Map(m =>
        {
            m.MapInheritedProperties();
            m.ToTable("WorkerMessage");
        });
        modelBuilder.Entity<WorkLog>().Map(m =>
        {
            m.MapInheritedProperties();
            m.ToTable("WorkLog");
        });
        modelBuilder.Entity<EntityAccess>().Map(m =>
        {
            m.MapInheritedProperties();
            m.ToTable("EntityAccess");
        });
        modelBuilder.Entity<Membership>().Map(m =>
        {
            m.MapInheritedProperties();
            m.ToTable("Membership");
        });
    }

public DbSet<Attachment> Attachments { get; set; }
    public DbSet<Blob> Blobs { get; set; }
    public DbSet<Message> Messages { get; set; }
    public DbSet<Parameter> Parameters { get; set; }
    public DbSet<ParameterValue> ParameterValues { get; set; }
    public DbSet<ProductStatus> ProductStatuses { get; set; }
    public DbSet<Profile> Profiles { get; set; }
    public DbSet<Schedule> Schedules { get; set; }
    public DbSet<User> Users { get; set; }
    public DbSet<UserGroup> UserGroups { get; set; }
    public DbSet<Worker> Workers { get; set; }
    public DbSet<WorkerMessage> WorkerMessages { get; set; }
    public DbSet<WorkLog> WorkLogs { get; set; }

// associations
    public DbSet<EntityAccess> EntityAccess { get; set; }
    public DbSet<Membership> Membership { get; set; }
}

1 个答案:

答案 0 :(得分:3)

您的问题不在上面的代码中,使用您的示例代码我构建了以下模型:

   public abstract class Entity 
    {
        public Guid? Id { get; set; }
        public bool IsDead { get; set; }
        public DateTime Created { get; set; }
        public DateTime Modified { get; set; }
        public ICollection<EntityAccess> AccessList { get; set; }
        public ICollection<Message> Discussion { get; set; }
        public User Owner { get; set; }
    }

    public class EntityAccess
    {
        public int Id { get; set; }
    }

    public class Message
    {
        public int Id { get; set; }
    }
    public class Structure : Entity
    {
        public string Property { get; set; }
    }
    public class User
    {
        public int Id { get; set; }
        public string Email { get; set; }
        public ICollection<UserGroup> Groups { get; set; }
        public byte[] Password { get; set; }
        public ICollection<Membership> Memberships { get; set; }
    }

    public class UserGroup
    {
        public int Id { get; set; }
    }

    public class Membership
    {
        public int Id { get; set; }
    }

    public class Model : DbContext
    {
        public DbSet<Structure> Structures { get; set; }
        public DbSet<User> Users { get; set; }
        public DbSet<EntityAccess> EntityAccesses { get; set; }
        public DbSet<Message> Messages { get; set; }
        public DbSet<UserGroup> UserGroups { get; set; }
        public DbSet<Membership> Memberships { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Structure>()
                .Map(m =>
                    {
                        m.MapInheritedProperties();
                        m.ToTable("Structure");
                    });
        }
    }

哪个生成了这个数据库: enter image description here

如您所见,在结构上有一个Owner_Id属性,它将所有者映射到结构表。