5

Environment

  • Framework 4.5
  • Entity Framework 6 (code First)

Model

Description

  • MainEntity One to many ChildEntity relationship
  • ChildEntity One to many recursive ChildEntity relationship

Model in code Snippet

public class MainEntity
{
    public long Id { get; set; }
    public virtual Collection<ChildEntity> ChildEntities { get; set; } 
}

public class ChildEntity
{
    public long Id { get; set; }
    public MainEntity ParentMainEntity { get; set; }
    public virtual Collection<ChildEntity> ChildEntities { get; set; } 
}

Note : A ChildEntity can only ONE level deep again ChildEntities as childeren.

Problem

I am able to persist this model. This seems to work fine. Only one issue. When I store a ChildEntity that has a parent ChildEntity. The MainEntity_id field is NULL, only the ParentChildEntityId is set. The reason I want to have the MainEntity_Id field always set is for performance queries.

How can I force that the MAINENTITY_ID field has always a value set in the deeper level?

user247702
  • 23,641
  • 15
  • 110
  • 157
Segers-Ian
  • 1,027
  • 10
  • 21
  • 1
    Why not make it `[Required]` and use a reference to the parent `ChildEntity` to retrieve its `MainEntity` id, which is always set if you do this for all childentities. – Stefan Aug 03 '14 at 13:49
  • I played around with the idea, adding a reference to the parent ChildEntity. Stores the same way as before. When I append the [Required] tag on the ParentMainEntity I stumble on a System.Data.Entity.Validation.DbEntityValidationException with "Validation failed for one or more entities. See 'EntityValidationErrors' property for more details." as message. No further intel or stacktrace that is useful to inspect that issue. @Stefan – Segers-Ian Aug 03 '14 at 14:08
  • Well, the validation exception is to be expected. You'll need some mechanism to set the `ParentMainEntity`, preferably when you create the object in the first place. – Stefan Aug 03 '14 at 15:05
  • By the way, if you need some way to get some usefull information from the validation exception, check out this post: http://stackoverflow.com/questions/15820505/dbentityvalidationexception-how-can-i-easily-tell-what-caused-the-error – Stefan Aug 03 '14 at 15:06
  • But I am 100% sure the ParentMainEntity is being set, I mad that sure and double checked by stepping in debug through it that the references where set. I'll take a look at your link @Stefan – Segers-Ian Aug 03 '14 at 15:20
  • If the ParentMainEntity is set, then its foreign key should be set by EF too. Probably there is a problem with the update then. You should post the code in which the `SaveChanges` method is called. – Dabblernl Aug 03 '14 at 20:20

2 Answers2

0

First:

You are giving yourself a hard time by leaving the foreign keys out of your POCO's. Adding a MainEntityId property to your ChildEntity will enable you to set the relation of new ChildEntities to a MainEntity.

Second:

var newChild =new ChildEntity();
parentEntity.ChildEntities.Add(newChild);
parentEntity.ParentMainEntity.ChildEntities.Add(newChild);

should work depending on how you have loaded the entities and which entities are or will be attached to the dbContext.

Dabblernl
  • 15,831
  • 18
  • 96
  • 148
0

You just need to define your relationship between MainEntity and ChildEntity to be required. You may do it in two ways:

  1. place [Required] attribute over ParentMainEntity property in ChildEntity
  2. use fluent api. In your DbContext class override OnModelCreating method and in it place code:

    modelBuilder.Entity().HasRequired(e => e.ParentMainEntity).WithMany(e => e.ChildEntities);

I would like as well to recommend you to make all your entities properties virtual. When all will be virtual then ef instead of working with your entity classes will create its own DynamicProxy classes deriving from your classes. They will provide additional tracking functionalities, they automatically change values of navigation properties if related objects changes etc. EF seems to deal much better with them. To use that functionality for newly created objects you will need to create them with context.ChildEntities.Create() method instead of using constructor. Of course as this adds constrain on your ChildEntity objects you may encounter exception during persisting data to db in SaveChanges. If the above change is the only one, that you've applied it is very probable that there is at least one ChildEntity object that do not have MainEntity object assigned to it.

mr100
  • 4,340
  • 2
  • 26
  • 38