0

Been stuck for hours with this weird problem. For some reason entity framework wont load the navigation properties of this 1 to many relationship, even though the generated SQL seems to be right, foreign key exists from SubItems to FrontPageItems:

CONSTRAINT [FK_dbo.SubItems_dbo.FrontPageItems_FrontPageItemId] 
    FOREIGN KEY ([FrontPageItemId]) 
        REFERENCES [dbo].[FrontPageItems] ([Id]) ON DELETE CASCADE

I have tried loading all frontpageitems with: _repo.Get();, but even though the SubItem table contains foreign keys referencing to FronPageItems table, no navigation properties gets loaded.

public class FrontPageItem : Logger, IEntity, IIsPublished
{
    public FrontPageItem()
    {
        SubItems = new HashSet<SubItem>();
    }

    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public bool IsPublished { get; set; }
    public virtual ICollection<SubItem> SubItems { get; set; }
}

    public class SubItem : Logger, IEntity, IIsPublished
{
    public SubItem()
    {
        FrontPageItem = new FrontPageItem();
    }
    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public string YoutubeUrl { get; set; }
    public virtual FrontPageItem FrontPageItem { get; set; }

    public int FrontPageItemId { get; set; }

    public bool IsPublished { get; set; }
}
public class SampleContext : IdentityDbContext<ApplicationUser>
{
    // throwIfV1Schema is used when upgrading Identity in a database from 1 to 2.
    // It's a one time thing and can be safely removed.
    public SampleContext()
        : base("DefaultConnection", throwIfV1Schema: false)
    {
    }

    public static SampleContext Create()
    {
        return new SampleContext();
    }

    // Define you conceptual model here. Entity Framework will include these types and all their references. 
    public IDbSet<FrontPageItem> FrontPageItem { get; set; }
    public IDbSet<SubItem> SubItems { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        // The DateTime type in .NET has the same range and precision as datetime2 in SQL Server.
        // Configure DateTime type to use SQL server datetime2 instead.
        modelBuilder.Properties<DateTime>().Configure(c => c.HasColumnType("datetime2"));

        base.OnModelCreating(modelBuilder);
    }
}

Btw it works if I remove the foreignkey property in SubItem:

public int FrontPageItemId { get; set; }

I have tried eager loading with include like this:

        var frontPageItems = _repo.AsQueryable().Include(o => o.SubItems).ToList();
3
  • What is _repo.Get()? Why do you expect it to load related entities for you automatically? Do you have lazy loading enabled? Commented Dec 4, 2015 at 9:35
  • Where do you tell the EF how it should handle your relation? I am missing something like HasRequired(si=> si.FrontPageItem ) .WithMany(fpi=> fpi.SubItems) .HasForeignKey(si=> si.FrontPageItemId ); Commented Dec 4, 2015 at 9:39
  • I use conventions, and it seems to generate the right SQL: CONSTRAINT [FK_dbo.SubItems_dbo.FrontPageItems_FrontPageItemId] FOREIGN KEY ([FrontPageItemId]) REFERENCES [dbo].[FrontPageItems] ([Id]) ON DELETE CASCADE Commented Dec 4, 2015 at 10:00

3 Answers 3

2

As DavidG mentioned, lazy loading is the default en EF. that means the properties only get loaded once you actually use them.

In order force inclusion of subitems you can use include like this

FrontPageItem.Include(x => x.SubItems).FirstOrDefault().

FrontPageItem here is your dbset. If you query it like this it will load the first frontpageitem with all subitems connected to it.

Update: If you follow the conventions stricktly you won't need to do this but if you have different names for your properties or want to have an explicit foreign key then you can configure the foreign key like this

modelBuilder.Entity<SubItem>() 
  .HasRequired(t => t.FrontPageItem) 
  .WithMany(t => t.SubItems) 
  .HasForeignKey(d => d.FrontPageItemId) 
  .WillCascadeOnDelete(true);
Sign up to request clarification or add additional context in comments.

5 Comments

Seems like conventions should handle this: msdn.microsoft.com/en-us/data/jj679962.aspx Btw i tried the Include trick. It didnt work, and it works now if i remove the public int FrontPageItemId { get; set; } property and let EF generate this foreignkey for me
you're right whitelatino, i updated my answer. You can use the modelbuilder part if you want to specify your own foreign key instead of letting EF generate it for you. otherwise convention should take care of it for you.
Btw _repo is a generic repository tugberkugurlu.com/archive/… Im sorry i tried all of this and none worked. I have read the top posts about this on google, nothing seems explain why my foreign key property is making me not being able load the navigation property.
If you have specific code that isn't working maybe you can update the question. Also can you show you exactly you tried your include trick if it's a generic repository?
I have updated, and to make thinks clear, it all works when i am not declaring a foreignkey property in SubItems, and that is the big mystery. It even works in serverexplore, since I cannot choose a SubItemId on FrontPageItems that doesnt exists.
1

LazyLoadingEnabled must be true, not false:

context.Configuration.LazyLoadingEnabled = true; true is the default if you don't set LazyLoadingEnabled at all.

And the SubItems property must be virtual to enable lazy loading for this property.

Or you can include the property directly in the query. You also need to set the FKby using the modelBuilder

    modelBuilder.Entity<SubItem>() 
  .HasRequired(t => t.FrontPageItem) 
  .WithMany(t => t.SubItems) 
  .HasForeignKey(d => d.FrontPageItemId) 
  .WillCascadeOnDelete(true);

Or by configuring Relationships using attributes

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

1 Comment

Sorry my conventions do exacly the same as your fluent api statement / Data Annotation.
0
    public SubItem()
{
    FrontPageItem = new FrontPageItem();
}

Was the problem. For some reason the constructor in SubItem was created this weird behavour, everything else was fine.

3 Comments

What's wrong with constructor? Not sure I understand what you mean by "Was the problem"...
Removing this constructor made me able to load navigation properties.
Ah ok. This is interesting and I hope some EF expert can explain why such a constructor would disable the navigation property loading. I guess it might override some default behaviour of EF but I would like to know the details of how EF implementation works. Why did you want to initialise the principle object anyway?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.