我首先使用代码在ASP.NET 5和EF 7中创建应用程序。我创建了我的类和DbContext
,以便在首次执行应用程序时创建数据库和表。
所以这是我的概念。我总共有3个表(Status
,PackageVersion
和DeploymentLog
)。
PackageVersion
和DeploymentLog
有一个外键StatusId
。因此Status
表可以包含多个DeploymentLogs
和PackageVersions
。
当我在Visual Studio中运行应用程序时,我得到一个例外。
在表'DeploymentLog'上引入FOREIGN KEY约束'FK_DeploymentLog_Status_StatusId'可能会导致循环或多个级联路径。指定ON DELETE NO ACTION或ON UPDATE NO ACTION,或修改其他FOREIGN KEY约束。
但是,当我从[Required]
和PackageVersion
类注释掉DeploymentLog
并在int?
这两个类中添加问号public int? StatusId { get; set; }
来制作它可选的;数据库和表生成没有任何问题。
这是我的代码:
packageversion
代码:
public class PackageVersion
{
public int Id { get; set; }
[Required]
[MaxLength(128)]
public string PackageName { get; set; }
[Required]
public int StatusId { get; set; }
public Status Status { get; set; }
public DateTime CreatedOn { get; set; }
public DateTime ModifiedOn { get; set; }
}
DeploymentLog
代码:
public class DeploymentLog
{
public int Id { get; set; }
[Required]
public int PackageVersionId { get; set; }
public PackageVersion PackageVersion { get; set; }
[Required]
public int StatusId { get; set; }
public Status Status { get; set; }
public DateTime CreatedOn { get; set; }
public DateTime ModifiedOn { get; set; }
}
Status
代码:
public class Status
{
public int Id { get; set; }
[Required]
[MaxLength(128)]
public string Name { get; set; }
}
DbContext
代码:
public class AutomationDBContext : DbContext
{
public AutomationDBContext()
{
Database.EnsureCreated();
}
public DbSet<Status> Status { get; set; }
public DbSet<PackageVersion> PackageVersions { get; set; }
public DbSet<DeploymentLog> DeploymentLogs { get; set; }
}
我也尝试在DBContext类中添加protected override onModelCreating
,但我仍然遇到同样的问题。这是代码:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<DeploymentLog>()
.HasOne(s => s.Status)
.WithOne()
.HasForeignKey<Status>(s => s.Id);
modelBuilder.Entity<PackageVersion>()
.HasOne(s => s.Status)
.WithOne()
.HasForeignKey<Status>(s => s.Id);
}
答案 0 :(得分:2)
为了在EF7中进行迁移,我必须做的就是删除StatusId
属性并创建导航属性virtual
。以下是我DbContext
的样子:
public class PackageVersion
{
public int Id { get; set; }
[Required]
[MaxLength(128)]
public string PackageName { get; set; }
public virtual Status Status { get; set; }
public DateTime CreatedOn { get; set; }
public DateTime ModifiedOn { get; set; }
}
public class DeploymentLog
{
public int Id { get; set; }
public virtual PackageVersion PackageVersion { get; set; }
public virtual Status Status { get; set; }
public DateTime CreatedOn { get; set; }
public DateTime ModifiedOn { get; set; }
}
public class Status
{
public int Id { get; set; }
[Required]
[MaxLength(128)]
public string Name { get; set; }
}
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public DbSet<Status> Status { get; set; }
public DbSet<PackageVersion> PackageVersions { get; set; }
public DbSet<DeploymentLog> DeploymentLogs { get; set; }
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
}
}
这会产生预期的ERD:
答案 1 :(得分:1)
您可以尝试使用Fluent API禁用级联删除(不能使用数据注释):
modelBuilder.Entity<PackageVersion>()
.HasOne(s => s.Status)
.WithOne()
.HasForeignKey<Status>(s => s.Id)
.WillCascadeOnDelete(false);
并且应该添加&#34;虚拟&#34;上
public virtual Status Status { get; set; }
答案 2 :(得分:0)
DeploymentLog有两个对Status的引用,一个直接和另一个间接引用整个PackageVersion。对我来说这是代码味道。
你可以通过不共享状态表来避免麻烦。由于你的模型现在,我可能会使用枚举,因为单个字符串属性没有那么多的权重来建模对象。作为替代方案,将使用Status作为查找表。