Truub February 2016

Entity Framework - Foreign Key not set (0 / null) but navigation property is not null

I've been stuck on this problem for quite some time. I'm using Fluent API Code-First to design a Database (EF 6.1). The problem is that when I add a new object, I can access entities in that object by their navigation property but the FK is 0 or NULL (in case of required and optional respectively). They are one-to-one relationships and I have tried both bidirectional and unidirectional.

Below is part of the code (Simplified, but only by including less entities):

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

    public int XmlDocId{ get; set; }
    public virtual XmlDoc XmlDoc { get; set; }

    public int? OtherXmlDocId{ get; set; }
    public virtual OtherXmlDoc OtherXmlDoc { get; set; }
}

public class XmlDoc 
{
    public int Id { get; set; }

    [Required]
    public string RawXml { get; set; }
}

public class OtherXmlDoc 
{
    public int Id { get; set; }

    [Required]
    public string RawXml { get; set; }
}

public class MyDbContext
{
    public virtual DbSet<Template> Templates { get; set; }
    public virtual DbSet<XmlDoc> XmlDocs { get; set; }
    public virtual DbSet<OtherXmlDoc> OtherXmlDocs { get; set; }


    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        ConfigureTemplates(modelBuilder);
    }

    private void ConfigureTemplates(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Template>()
            .HasRequired<XmlDoc>(c => c.XmlDoc)
            .WithRequiredPrincipal()
            .WillCascadeOnDelete(true);

        // XML SCHEMA, delete with TT (optional)
        modelBuilder.Entity<Template>()
            .HasOptional<OtherXmlDoc>(c => c.OtherXmlDoc)
            .WithOptionalPrincipal()
            .WillCascadeOnDelete(true);
    }
}

Now when I seed the database in my configuration files all the entities are loaded correctly (FK's correspond etc.)

Answers


PM. February 2016

See if mentioning foreign key explicitly helps:

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

public int XmlDocId{ get; set; }

[ForeignKey("XmlDocId")]
public virtual XmlDoc XmlDoc { get; set; }

public int? OtherXmlDocId{ get; set; }

[ForeignKey("OtherXmlDocId")]
public virtual OtherXmlDoc OtherXmlDoc { get; set; }
}


Ivan Stoev February 2016

In your one-to-one relationships, Template is the principal while XmlDoc and OtherXmlDoc are the dependents. Which means that Template does not have foreign keys, but the opposite - the PK Id column in XmlDoc / OtherXmlDoc is also a FK to Template. Hence XmlDocId and OtherXmlDocId columns do not play any role in the relationships and EF treats them as regular data columns and does not synchronize them with the navigation properties.

Shortly, they are redundant and you should simply remove them and use the navigation properties (after SaveChanges, the Id of a non null navigation property will always be the same as the entity.Id). Also it's good to add the inverse navigation properties, so the final model/setup could be like this

public class Template
{
    public int Id { get; set; }
    public virtual XmlDoc XmlDoc { get; set; }
    public virtual OtherXmlDoc OtherXmlDoc { get; set; }
}

public class XmlDoc
{
    public int Id { get; set; }
    [Required]
    public string RawXml { get; set; }
    public virtual Template Template { get; set; }
}

public class OtherXmlDoc
{
    public int Id { get; set; }
    [Required]
    public string RawXml { get; set; }
    public virtual Template Template { get; set; }
}

private void ConfigureTemplates(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Template>()
        .HasRequired<XmlDoc>(t => t.XmlDoc)
        .WithRequiredPrincipal(d => d.Template)
        .WillCascadeOnDelete(true);

    modelBuilder.Entity<Template>()
        .HasOptional<OtherXmlDoc>(t => t.OtherXmlDoc)
        .WithOptionalPrincipal(d => d.Template)
        .WillCascadeOnDelete(true);
}

Post Status

Asked in February 2016
Viewed 1,644 times
Voted 9
Answered 2 times

Search




Leave an answer