Optional one to one relationship in EF 6

c# entity-framework entity-framework-6

Question

I am using Entity Framework 6 with code first.

The ideal scenario would be the User creates a PrintType (e.g. "Business Card") and then he created multiple Layouts for this PrintType (e.g. "Center", "Left") an finally he creates a template called "Business Card with flowers". 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.

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'. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations.

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);
    }
1
0
7/18/2018 7:21:18 AM

Popular Answer

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:

Method 1:

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

Method 2:

and if you are going to set the default template and Layout yourself in your code, you can set the dependents to required. you can get this done by putting a Required annotation on your depended ends like this:

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:

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.

0
7/18/2018 7:13:19 AM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow