简体   繁体   English

EF 6中的可选一对一关系

[英]Optional one to one relationship in EF 6

I am using Entity Framework 6 with code first. 我首先使用带有代码的Entity Framework 6。

The ideal scenario would be the User creates a PrintType (eg "Business Card") and then he created multiple Layouts for this PrintType (eg "Center", "Left") an finally he creates a template called "Business Card with flowers". 理想的情况是,用户创建一个PrintType(例如“名片”),然后为该PrintType创建多个布局(例如“ Center”,“ Left”),最后他创建一个名为“带花的名片”的模板。 As soon he is creating this template the program should create a default-layout for THIS template. 他创建此模板后,程序应立即为该模板创建默认布局。

So there should be an optional FK that is only set when it is an default-layout for a template. 因此,应该有一个仅在它是模板的默认布局时才设置的可选FK。

I hope you could follow me. 我希望你能跟随我。

When I want to create a migration with the code below i get the following error: 当我想使用下面的代码创建迁移时,出现以下错误:

Unable to determine the principal end of an association between the types 'xxx.Entities.Template' and 'xxx.Entities.Layout'. 无法确定类型“ xxx.Entities.Template”和“ xxx.Entities.Layout”之间的关联的主要终点。 The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations. 必须使用关系流利的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);
    }

If I am following you, you need a relation in Fluent API that makes your Foreign key optional, In your DbContext class you can get this done with FluentAPI like this: 如果我关注您,则需要Fluent API中的一个关系,该关系使您的外键成为可选项,在DbContext类中,您可以使用FluentAPI来完成此操作,如下所示:

Method 1: 方法1:

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

Method 2: 方法2:

and if you are going to set the default template and Layout yourself in your code, you can set the dependents to required. 如果要在代码中设置默认模板和Layout,则可以将依赖项设置为required。 you can get this done by putting a Required annotation on your depended ends like this: 您可以通过在您的依赖端上放置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; }
}

and

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

and your Fluent API code to avoid cascade delete issue: 和您的Fluent API代码,以避免级联删除问题:

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

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

it gives you the flexibility to play with the non-required fields too. 它也使您可以灵活地处理非必填字段。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM