【问题标题】:MapInheritedProperties() not mapping inherited foreign key propertiesMapInheritedProperties() 不映射继承的外键属性
【发布时间】:2012-09-14 14:18:28
【问题描述】:

这是我的实体类:

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 对象,没有注释,没有构造函数,什么都没有。例如,这是 User 实体:

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; }
}

【问题讨论】:

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


    【解决方案1】:

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

       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");
                        });
            }
        }
    

    生成了这个数据库:

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

    【讨论】:

    • 有趣,我会调查看看还有什么可能导致它,粘贴我的整个项目似乎有点过头了,但我可能会在这里找到更多相关信息。
    • 一些附加信息。只有继承的外键没有被映射,我尝试使用另一个实体作为类型添加另一个属性,它不起作用。添加另一个 int 属性没有问题。
    • 我知道你不想发布你的整个项目 - 你的模型有多大,你可以发布吗?我无法用这个小子集复制您的问题。
    • 我的模型中有很多实体,如果我想发布整个项目或整个模型,我应该复制粘贴所有内容吗?
    • 我发现你的代码和我之间有一个区别,尽管它可能没有区别。我所有的 id 都是 Guid?,你的大部分都是 int。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-24
    • 2011-03-01
    相关资源
    最近更新 更多