【问题标题】:Optional one to one relationship in EF 6EF 6 中的可选一对一关系
【发布时间】:2018-07-18 15:21:18
【问题描述】:

我首先使用带有代码的 Entity Framework 6。

理想的场景是用户创建一个 PrintType(例如“Business Card”),然后他为此 PrintType 创建多个布局(例如“Center”、“Left”),最后他创建了一个名为“Business Card with花卉”。一旦他创建了这个模板,程序应该为这个模板创建一个默认布局。

所以应该有一个可选的 FK,只有当它是模板的默认布局时才设置。

希望你能关注我。

当我想使用下面的代码创建迁移时,我收到以下错误:

无法确定之间关联的主体端 类型 'xxx.Entities.Template' 和 'xxx.Entity.Layout'。这个的主要目的 关联必须使用任一显式配置 关系流式 API 或数据注释。

public class PrintType
{
    public int Id { get; set; }
    public string Title { get; set; }

    public virtual ICollection<Template> Templates { get; set; }
    public virtual ICollection<Layout> Layouts { get; set; }
}

public class Layout
{
    public int Id { get; set; }
    public string Title { get; set; }

    [Required]
    public virtual PrintType PrintType { get; set; }
    public Template Template { get; set; }
}

public class Template
{
    public int Id { get; set; }
    public string Title { get; set; }

    [Required]
    public virtual PrintType PrintType { get; set; }

    [Required]
    public Layout Layout { get; set; }
}

protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Layout>().HasOptional(a => a.Template).WithOptionalDependent().WillCascadeOnDelete(false);
    }

【问题讨论】:

  • 您只能使用 Fluent API 映射为布局类型创建动态 FK。
  • 关系的哪一边应该包含外键?更一般地说,我认为你应该退后一步,重新评估你的要求。我情不自禁——你的关系模型在我看来是错误的(只是一种感觉)
  • 你能更详细地解释一下布局的作用吗?布局可以独立于模板存在吗?多个模板可以具有相同的布局吗?什么是“默认”布局?它真的是一个后备,还是更像是一个初始布局,当用户开始配置更多细节时会改变?

标签: c# entity-framework entity-framework-6


【解决方案1】:

如果我在关注你,你需要 Fluent API 中的一个关系,使你的外键成为可选的,在你的 DbContext 类中,你可以像这样使用 FluentAPI 完成此操作:

方法一:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<A>()
            .HasOptional(a => a.MyB)
            .WithOptionalDependent()
            .WillCascadeOnDelete(true); // or false depends
    }

方法二:

如果您要在代码中自己设置默认模板和布局,您可以将依赖项设置为必需。您可以通过在您的依赖端添加 Required 注释来完成此操作,如下所示:

public class Layout
{
    public int Id { get; set; }
    public string Title { get; set; }

    [Required]
    public virtual PrintType PrintType { get; set; }
    public Template Template { get; set; }
}

public class Template
{
    public int Id { get; set; }
    public string Title { get; set; }

    [Required]
    public virtual PrintType PrintType { get; set; }
    [Required]
    public Layout Layout { get; set; }
}

以及您的 Fluent API 代码以避免级联删除问题:

modelBuilder.Entity<Child1>()
    .HasRequired(c => c.navigationpropertyhere)
    .WithMany()
    .WillCascadeOnDelete(false);

modelBuilder.Entity<Child2>()
    .HasRequired(s => s.navigationpropertyhere)
    .WithMany()
    .WillCascadeOnDelete(false);

它也让您可以灵活地使用非必填字段。

【讨论】:

  • 但是,[Required] 不是可选的 :)
  • @grek40 对,我把它弄混了,让我编辑问题,谢谢指出:)
  • 您好,我更新了 Start-Post ... 现在我收到以下错误:在表 'Vorlages' 上引入 FOREIGN KEY 约束 'FK_dbo.Vorlages_dbo.Layouts_Layout_Id' 可能会导致循环或多个级联路径。指定 ON DELETE NO ACTION 或 ON UPDATE NO ACTION,或修改其他 FOREIGN KEY 约束。无法创建约束或索引。查看以前的错误。
  • @Mathis 请在删除您的Required 属性或您的 Fluent API 代码后尝试一下。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-10
  • 1970-01-01
  • 2021-11-18
  • 2015-07-29
  • 2021-07-21
相关资源
最近更新 更多