我来自nHibernate,正在尝试创建一个具有2列复合键的实体,其中两列均为外键。
例如,我有一个UserRole表,它是(UserId Guid,RoleId Guid)。我想建模为
public class UserRole
{
public User User { get; set; }
public Role Role { get; set; }
}
EF似乎并不喜欢这个想法。似乎要我也加上Guid UserId {get;set;}
和Guid RoleId { get; set; }
。通过在dbcontext中定义模型,我设法解决了FK部分的处理问题,如下所示:
modelBuilder.Entity<UserRole>()
.HasRequired(x => x.Role)
.WithRequiredPrincipal()
.Map(x => x.MapKey("RoleId"));
modelBuilder.Entity<UserRole>()
.HasRequired(x => x.User)
.WithRequiredPrincipal()
.Map(x => x.MapKey("UserId"));
我希望我可以成为一个惯例。但是,当我也尝试这样做时:
modelBuilder.Entity<UserRole>().HasKey(x => new { x.User, x.Role });
它在运行时出现以下问题:
The property 'User' cannot be used as a key property on the entity 'Paroxysm.Domain.UserRole' because the property type is not a valid key type. Only scalar types, string and byte[] are supported key types.
仅供参考,这是在nHibernate byCode映射中完成的(如下所示)(略有不同):
public class ProjectUserProfileMap : ClassMap<ProjectUserProfile>
{
public ProjectUserProfileMap()
{
CompositeId()
.KeyReference(x => x.User, "UserId")
.KeyReference(x => x.Project, "ProjectId");
ReadOnly();
References(x => x.User, "UserId");
References(x => x.Project, "ProjectId");
Map(x => x.IsActive);
Map(x => x.ActivatedUtcDate).Not.Nullable().CustomType<NHibernate.Type.UtcDateTimeType>();
Map(x => x.InvitedUtcDate).Not.Nullable().CustomType<NHibernate.Type.UtcDateTimeType>();
Table("ProjectUserProfile");
}
}
太简单!顺便说一句,EF似乎也不支持几乎没有CustomType UTC行为。
问题实际上与以下事实无关:我有一个复合键,但只有一个单列PK(也为FK)会是一个奇怪的情况(1:1相对)。
因此,我想我想肯定地知道这是否可以在EF6中完成。该错误消息肯定表明其不可行。有人可以确认吗?
您可以实现此目的,但前提是您必须添加到UserRole 2外键属性:RoleId和UserId。这是因为HasKey不提供任何映射功能-只能在实体类中存在的属性上定义它。似乎EF强制将所有主键列始终定义为类中的具体属性,在这些类中,外键列可能未定义相应的属性。因此,要实现您想要的目标,您需要定义UserRole,如下所示:
public class UserRole
{
public User User { get; set; }
public int UserId { get; set; }
public Role Role { get; set; }
public int RoleId { get; set; }
}
modelBuilder.Entity<UserRole>()
.HasRequired(x => x.Role)
.WithRequiredPrincipal()
.HasForeignKey(x => x.RoleId);
modelBuilder.Entity<UserRole>()
.HasRequired(x => x.User)
.WithRequiredPrincipal()
.HasForeignKey(x => x.UserId);
modelBuilder.Entity<UserRole>().HasKey(x => new { x.UserId, x.RoleId });
您发布的确切情况可能会通过多对多关系来实现:
modelBuilder.Entity<User>()
.HasMany(x => x.Roles)
.WithMany()
.Map(m =>
{
m.ToTable("UserRole");
m.MapLeftKey("UserId");
m.MapRightKey("RoleId");
});
这样,您将获得在UserId和RoleId上定义了主键的UserRole表。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句