使用代码优先和迁移在两个 class 之间创建 1-1 关系
creating 1-1 relationship between two class using code first and migration
好吧,这是我第一次尝试先使用代码在两个 table 之间创建 1-1 关系。我在网上寻求了一些帮助,并遇到了以下 classes 映射。
比我运行迁移,发现不对。例如。迁移表明 StudentDetails 的主键是来自 Student table 的 Id
,而我希望拥有主键 StudentId。此外,正在以相反的方式创建外键。
请有人指出这里有什么问题,或者是我认为错了。
我需要使用 student
class 中的 Id
作为 StudentDetails class 中的外键。
public class Student
{
public bool isPass{get;set;}
public virtual StudentReport Report { get; set; }
}
public class StudentReport
{
[Key, ForeignKey("Student")]
public Guid Id { get; set; }
public Guid? StudentReportId { get; set; }
public string RollNumber { get; set; }
public string StudentType { get; set; }
public virtual Student Student { get; set; }
}
当我 运行 我的迁移时,我得到以下看起来不太好的结果。
public partial class StudentReport : DbMigration
{
public override void Up()
{
CreateTable(
"dbo.StudentReport",
c => new
{
Id = c.Guid(nullable: false, identity: true),
StudentReportId = c.Guid(),
RollNumber = c.String(),
StudentType = c.String(),
})
.PrimaryKey(t => t.Id)
.ForeignKey("dbo.Student", t => t.Id)
.Index(t => t.Id);
}
在一对一关系中,一端必须是主体,另一端是从属。如果您要在依赖实体中声明 FK 属性,EF 要求 属性 也应该是 PK:
public class Principal
{
[Key]
public int Id{get;set;}
public virtual Dependent Dependent{get;set;}
}
public class Dependent
{
[Key, ForeignKey("Principal")]
public int PrincipalId{get;set;}
public virtual Principal Principal{get;set;}
}
如果你想让两个实体都有自己的 PK,并且还使用 Student
实体中的 Id
作为 StudentReport
class 中的 FK,那么你可以尝试使用此模型:
public class Student
{
[Key]
public Guid Id { get; set; }
public bool isPass{get;set;}
}
public class StudentReport
{
[Key]
public Guid StudentReportId{ get; set; }
[ForeignKey("Student")]
public Guid StudentId { get; set; }
public string RollNumber { get; set; }
public string StudentType { get; set; }
public virtual Student Student { get; set; }
}
我想您真正需要的是一对多关系,因为一个学生可能有 0 个或多个报告。
检查此 link。它可以帮助您更好地理解如何使用 FK 属性和默认代码优先的名称约定。
更新 1
如果您想创建一对一关系并且两个实体都有自己的 PK,那么由于我在开头解释的限制,您不能在依赖实体中定义 FK 属性我的答案。您需要的解决方案可能是使用 Required
属性并删除 FK 属性:
public class Student
{
[Key]
public Guid Id { get; set; }
public bool isPass{get;set;}
public virtual StudentReport StudentReport { get; set; }
}
public class StudentReport
{
[Key]
public Guid StudentReportId{ get; set; }
public string RollNumber { get; set; }
public string StudentType { get; set; }
[Required]
public virtual Student Student { get; set; }
}
更新 2
你确定吗?我得到的迁移代码是这样的:
AddForeignKey("dbo.StudentReports", "StudentReportId", "dbo.Students", "Id");
这还不行,因为 Code First 仍然按照惯例将 StudentReport
的 PK 配置为 FK。为避免这种情况,您可以将此 Fluent Api 配置添加到您的上下文中:
modelBuilder.Entity<StudentReport>()
.HasRequired(sr => sr.Student)
.WithOptional(s => s.StudentReport)
.Map(c=>c.MapKey("Student_Id"));
这样 Code First 将生成此迁移代码:
AddColumn("dbo.StudentReports", "Student_Id", c => c.Guid(nullable: false));
CreateIndex("dbo.StudentReports", "Student_Id");
AddForeignKey("dbo.StudentReports", "Student_Id", "dbo.Students", "Id");
好吧,这是我第一次尝试先使用代码在两个 table 之间创建 1-1 关系。我在网上寻求了一些帮助,并遇到了以下 classes 映射。
比我运行迁移,发现不对。例如。迁移表明 StudentDetails 的主键是来自 Student table 的 Id
,而我希望拥有主键 StudentId。此外,正在以相反的方式创建外键。
请有人指出这里有什么问题,或者是我认为错了。
我需要使用 student
class 中的 Id
作为 StudentDetails class 中的外键。
public class Student
{
public bool isPass{get;set;}
public virtual StudentReport Report { get; set; }
}
public class StudentReport
{
[Key, ForeignKey("Student")]
public Guid Id { get; set; }
public Guid? StudentReportId { get; set; }
public string RollNumber { get; set; }
public string StudentType { get; set; }
public virtual Student Student { get; set; }
}
当我 运行 我的迁移时,我得到以下看起来不太好的结果。
public partial class StudentReport : DbMigration
{
public override void Up()
{
CreateTable(
"dbo.StudentReport",
c => new
{
Id = c.Guid(nullable: false, identity: true),
StudentReportId = c.Guid(),
RollNumber = c.String(),
StudentType = c.String(),
})
.PrimaryKey(t => t.Id)
.ForeignKey("dbo.Student", t => t.Id)
.Index(t => t.Id);
}
在一对一关系中,一端必须是主体,另一端是从属。如果您要在依赖实体中声明 FK 属性,EF 要求 属性 也应该是 PK:
public class Principal
{
[Key]
public int Id{get;set;}
public virtual Dependent Dependent{get;set;}
}
public class Dependent
{
[Key, ForeignKey("Principal")]
public int PrincipalId{get;set;}
public virtual Principal Principal{get;set;}
}
如果你想让两个实体都有自己的 PK,并且还使用 Student
实体中的 Id
作为 StudentReport
class 中的 FK,那么你可以尝试使用此模型:
public class Student
{
[Key]
public Guid Id { get; set; }
public bool isPass{get;set;}
}
public class StudentReport
{
[Key]
public Guid StudentReportId{ get; set; }
[ForeignKey("Student")]
public Guid StudentId { get; set; }
public string RollNumber { get; set; }
public string StudentType { get; set; }
public virtual Student Student { get; set; }
}
我想您真正需要的是一对多关系,因为一个学生可能有 0 个或多个报告。
检查此 link。它可以帮助您更好地理解如何使用 FK 属性和默认代码优先的名称约定。
更新 1
如果您想创建一对一关系并且两个实体都有自己的 PK,那么由于我在开头解释的限制,您不能在依赖实体中定义 FK 属性我的答案。您需要的解决方案可能是使用 Required
属性并删除 FK 属性:
public class Student
{
[Key]
public Guid Id { get; set; }
public bool isPass{get;set;}
public virtual StudentReport StudentReport { get; set; }
}
public class StudentReport
{
[Key]
public Guid StudentReportId{ get; set; }
public string RollNumber { get; set; }
public string StudentType { get; set; }
[Required]
public virtual Student Student { get; set; }
}
更新 2
你确定吗?我得到的迁移代码是这样的:
AddForeignKey("dbo.StudentReports", "StudentReportId", "dbo.Students", "Id");
这还不行,因为 Code First 仍然按照惯例将 StudentReport
的 PK 配置为 FK。为避免这种情况,您可以将此 Fluent Api 配置添加到您的上下文中:
modelBuilder.Entity<StudentReport>()
.HasRequired(sr => sr.Student)
.WithOptional(s => s.StudentReport)
.Map(c=>c.MapKey("Student_Id"));
这样 Code First 将生成此迁移代码:
AddColumn("dbo.StudentReports", "Student_Id", c => c.Guid(nullable: false));
CreateIndex("dbo.StudentReports", "Student_Id");
AddForeignKey("dbo.StudentReports", "Student_Id", "dbo.Students", "Id");