这是我的实体类:
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; }
}
答案 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");
});
}
}
哪个生成了这个数据库:
如您所见,在结构上有一个Owner_Id属性,它将所有者映射到结构表。