[英]One-to-one Mapping issue with NHibernate/Fluent: Foreign Key not updateing
[英]One-To-One Mapping issue
我的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
的可选属性,并将SerialNumber
User
添加到UserProfile
时自动设置?
默认情况下,在一对一关系中,Entity Framework要求依赖项上的外键也是主键。 这可能是因为实体框架仅对主键设置了唯一约束(或者说,由于它是主键,因此存在唯一约束)。 在数据库的级别上,一对一不映射到关系的两侧,即在两个表上都没有创建外键。 当您考虑参照完整性如何工作时,这是有道理的:如果关系的一方被删除,则会导致另一方的数据库分离,导致一种无限循环。
因此,外键被添加到依赖项,在这种情况下,就像你在这里一样,这就是具有所需导航属性的结尾:你的SerialNumber
模型。 这意味着要真正创建一对一而不是一对多, SerialNumber
上的密钥需要是User_UserId
(自动生成的外键列,因为您没有手动指定外键属性) )。 要以这种方式进行设置,您的模型将如下所示:
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; }
...
}
或者使用Fluent API:
modelBuilder.Entity<SerialNumber>()
.HasRequired(m => m.User)
.WithOptional(m => m.Serial);
(您需要省略[Key]
数据注释,以便EF可以创建外键,它们是表的主键。)
但是,这使您在Code
属性上没有唯一约束。 您当然可以在表上手动设置此约束,或者如果您不使用自动迁移,则可以更改迁移以创建约束:
CreateIndex("dbo.SerialNumbers", "Code", unique: true);
这里的问题是实体框架不会为您处理唯一的验证。 因此,您需要在代码中手动维护完整性(即,尝试使用您要保存的Code
查找SerialNumber
,并且只有在您从查询中得不到任何内容时才保存它)。
我知道,这是一种痛苦,但就目前而言,这就是你所能做的一切。 希望EF能够最终解决未来版本中的独特性问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.