实体框架7一对多的关系

时间:2016-02-09 17:14:21

标签: c# asp.net asp.net-mvc entity-framework

我首先使用代码在ASP.NET 5和EF 7中创建应用程序。我创建了我的类和DbContext,以便在首次执行应用程序时创建数据库和表。

所以这是我的概念。我总共有3个表(StatusPackageVersionDeploymentLog)。

PackageVersionDeploymentLog有一个外键StatusId。因此Status表可以包含多个DeploymentLogsPackageVersions

当我在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);
}

3 个答案:

答案 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:

enter image description here

答案 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; }

检查一下 http://msdn.microsoft.com/en-US/data/jj591620

答案 2 :(得分:0)

DeploymentLog有两个对Status的引用,一个直接和另一个间接引用整个PackageVersion。对我来说这是代码味道。
你可以通过不共享状态表来避免麻烦。由于你的模型现在,我可能会使用枚举,因为单个字符串属性没有那么多的权重来建模对象。作为替代方案,将使用Status作为查找表。