我的SQL理解非常基础,我来自NHibernate的世界,所以我对这个问题感到很困惑......
我有两个班级:
public class UserProfile
{
public UserProfile() { }
[Key]
public int UserId { get; set; }
public string UserName { get; set; }
public SerialNumber Serial { get; set; }
// Other properties
}
和
public class SerialNumber
{
public SerialNumber()
{
// My code that creates a unique Code
}
[Key]
public string Code { get; set; }
public UserProfile User { get; set; }
// Other Properties
}
我有这个
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// Other modelBuilder stuff
modelBuilder.Entity<UserProfile>()
.HasOptional(s => s.Serial)
.WithRequired(u => u.User);
}
运行Add-Migration
后,我明白了:
public override void Up()
{
DropForeignKey("dbo.UserProfile", "Serial_Code", "dbo.SerialNumbers");
DropIndex("dbo.UserProfile", new[] { "Serial_Code" });
RenameColumn(table: "dbo.SerialNumbers", name: "Serial_Code", newName: "User_UserId");
AddForeignKey("dbo.SerialNumbers", "User_UserId", "dbo.UserProfile", "UserId");
CreateIndex("dbo.SerialNumbers", "User_UserId");
}
public override void Down()
{
// Inverse of above
}
运行Update-Database
后,我收到错误消息:
"Either the parameter @objname is ambiguous or the claimed @objtype (COLUMN) is wrong."
我可以通过Add-Migration
生成的代码告诉我出错了,因为我的db表甚至没有名称为"Serial_Code"
的列
我需要Code
成为我的Key
,因为EntityFramework没有选项可以将列强制为Unique
,除非使其成为密钥。
如何Serial
成为UserProfile
中的User
和SerialNumber
的可选属性,以便在UserProfile
添加到{{1}}后自动设置?< / p>
答案 0 :(得分:4)
默认情况下,在一对一关系中,Entity Framework要求依赖项上的外键也是主键。这可能是因为实体框架仅对主键设置了唯一约束(或者说,由于它是主键,因此存在唯一约束)。在数据库的级别上,一对一不映射到关系的两侧,即在两个表上都没有创建外键。当您考虑参照完整性如何工作时,这是有道理的:如果关系的一方被删除,则会导致另一方的数据库分离,导致一种无限循环。
因此,将外键添加到依赖项中,在此情况下,如果您具有所需的导航属性,则为{1}}模型。这意味着要真正创建一对一而不是一对多,SerialNumber
上的密钥需要SerialNumber
(自动生成的外键列,因为你没有不要手动指定外键属性。要以这种方式进行设置,您的模型将如下所示:
User_UserId
或使用Fluent API:
public class UserProfile
{
[Key]
public int UserId { get; set; }
public SerialNumber Serial { get; set; }
...
}
public class SerialNumber
{
[Key]
[ForeignKey("User")]
public int UserId { get; set; }
public UserProfile User { get; set; }
...
}
(您需要取消modelBuilder.Entity<SerialNumber>()
.HasRequired(m => m.User)
.WithOptional(m => m.Serial);
数据注释,以便EF可以创建外键,它们是表的主键。)
但是,这使您在[Key]
属性上没有唯一约束。您当然可以在表上手动设置此约束,或者如果您不使用自动迁移,则可以更改迁移以创建约束:
Code
这里的问题是Entity Framework不会为您处理独特的验证。因此,您需要在代码中手动维护完整性(即,尝试使用您要保存的CreateIndex("dbo.SerialNumbers", "Code", unique: true);
查找SerialNumber
,并且只有在您没有得到任何内容时才保存它从查询中回来)。
这是一种痛苦,我知道,但就目前而言,这就是你所能做的一切。希望EF能够在未来版本中最终解决其独特性。