我正在使用.Net Framework 4.0开发一个实体框架代码优先(v.4.4.0.0)C#库。
我不知道如何设置零对一关系。我的模型如下:
Talk
只能由一位用户(StarterUserId
)创建
Talk
只能有一个收件人用户(RecepientUserId
)或只有一个用户组RecipientGroupId
)。
注意:这意味着如果RecepientUserId
不为空,则RecipientGroupId
为空;如果RecepientUserId
为空,则RecipientGroupId
不为空。
user
可以是零或n Talks
的收件人,但group
可以是零或一Talk
。
这是 Talk 类:
[DataContract]
public class Talk
{
[DataMember]
public int TalkId { get; set; }
[DataMember]
public int StarterUserId { get; set; }
[DataMember]
public int? RecipientUserId { get; set; }
[DataMember]
[ForeignKey("RecipientGroup")]
public int? RecipientGroupId { get; set; }
public DateTime DateUtcStarted { get; set; }
[DataMember]
public string DateStarted
{
get
{
return DateUtcStarted.ToString("dd/MM/yyyy HH:mm");
}
set
{
DateUtcStarted = DateTime.Parse(value);
}
}
public User StarterUser { get; set; }
public User RecipientUser { get; set; }
public Group RecipientGroup { get; set; }
}
使用 TalkConfiguration 类:
class TalkConfiguration : EntityTypeConfiguration<Talk>
{
public TalkConfiguration()
{
Property(t => t.StarterUserId).IsRequired();
Property(t => t.RecipientUserId).IsOptional();
Property(t => t.RecipientGroupId).IsOptional();
Property(t => t.DateUtcStarted).IsRequired();
Ignore(t => t.DateStarted);
HasRequired(t => t.StarterUser).
WithMany(u => u.TalksStarted).
HasForeignKey(t => t.StarterUserId);
HasOptional(t => t.RecipientUser).
WithMany(u => u.InTalks).
HasForeignKey(t => t.RecipientUserId);
HasOptional(t => t.RecipientGroup).WithOptionalDependent(g => g.GroupTalk);
}
}
这是Group
类:
[DataContract]
public class Group
{
[DataMember]
public int GroupId { get; set; }
[ ... ]
public Talk GroupTalk { get; set; }
}
GroupConfiguration
类:
class GroupConfiguration : EntityTypeConfiguration<Group>
{
public GroupConfiguration()
{
[ ... ] // Nothing related to GroupTalk
}
}
通过这些类和配置,我在数据库中获得了这个Talk
表:
我想将Talk.RecipientGroupId
作为 FOREIGN KEY 设为Group.GroupId
。但是,此模型会创建另一列Talk.RecipientGroup_GroupId
作为 FOREIGN KEY 到Group.GroupId
。而且,我不希望这样。
我该怎么做?
答案 0 :(得分:1)
可选:可选的一对一关系映射为独立关联,而不是外键关联,这意味着您不能在模型类中拥有外键属性。这就是为什么你不能在HasForeignKey
之后链接WithOptionalDependent
。而且我非常确定[ForeignKey]
上的RecipientGroupId
属性被忽略了,EF认为RecipientGroupId
是一个普通的标量属性而没有任何关系。
在数据库模式本身中,该关系具有外键。这是您使用自动生成的默认名称看到的那个:RecipientGroup_GroupId
。但是不支持将此外键映射到属性。但是,我认为您可以使用MapKey
HasOptional(t => t.RecipientGroup)
.WithOptionalDependent(g => g.GroupTalk)
.Map(m => m.MapKey("RecipientGroupId"));
如果你这样做,你必须从RecipientGroupId
类删除Talk
属性,否则EF会抱怨两个具有相同名称的冲突列。
我相信,可选:可选是唯一的一对一关系,它们是独立关联,所有其他关键是外键关联,其中外键属性同时是主键属性(根据Arthur Vickers的回答)在this thread的底部。使用可选:可选关系,这是不可能的,因为主键属性不能为空。
由于您的RecipientGroupId
具有[DataMember]
属性,因此您希望在某些服务边界上传输该值,因此出于某种原因需要外键作为属性值。在这种情况下,我选择的解决方法是将Talk<->Group
关系映射为一对多关系,而Group
类中没有任何导航属性(将其映射到无参数{{1}调用then)或使用集合导航属性,然后在业务逻辑中确保此集合不能包含多个元素。