5

So Say I have 2 entities, Post and PostHistory. Whenever I create or edit a post, I want to create an exact copy of it as PostHistory to log all changes made to a post. Say the post entity has the following definition:

public class Post
{
    public int Id { get; set; }
    public string Text { get; set; }
    public virtual ICollection<PostHistory> PostHistory{ get; set; }
}

The problem comes when I create my first Post. For example, if I try this:

Post post = new Post { Text = "Blah" };
context.Posts.Add(post);
PostHistory history = new PostHistory { Text = "Blah"};
context.PostHistory.Add(history);
post.PostHistory.Add(history);

That will fail because since both post and history are new entities, Post.PostHistory is null due to it not having been initialized yet. The only way I can see to do this is to first commit post to the db, then commit history to the database, but I don't see why performing 2 separate inserts should be necessary for this.

If I have a constructor that initializes the ICollection to a List<T> everything works fine, but forcing the implementation to List<T> causes other issues, and almost no code-first tutorials do this forced initiation.

So what's the best way to handle this situation?

KallDrexx
  • 27,229
  • 33
  • 143
  • 254

1 Answers1

4

You can initialize the list in the client code itself:

Post post = new Post 
{ 
    Text = "Blah" 
    PostHistory = new List() 
    { 
        new PostHistory { Text = "Blah" }
    }
};        
context.Posts.Add(post);
context.SaveChanges();

However, there is nothing wrong with initializing the collection inside the constructor and it is actually recommended because it saves you from having to initialize it in all the client codes.

Morteza Manavi
  • 33,026
  • 6
  • 100
  • 83
  • Initializing the collection as a list works but it's not a good option. The reason is that you cant convert a List to an EntityCollection (so I can check if the collection has been eager loaded for example). – KallDrexx Feb 18 '11 at 01:22
  • How do you check if the collection is eager loaded with `EntityCollection`? – Morteza Manavi Feb 18 '11 at 01:54
  • The `EntityCollection` class has an `IsLoaded` property – KallDrexx Feb 18 '11 at 03:12
  • And that's only valid when you have entityobjects in place. When using POCOs, the last thing you want to do is to tightly coupled them to the EF which is a very well known anti-pattern. – Morteza Manavi Feb 18 '11 at 03:43
  • I agree with not wanting them coupled with EF, I'm just trying to find a way to let the DB system create the `ICollection`, but it's looking less and less like that's possible – KallDrexx Feb 18 '11 at 04:29
  • @KallDrexx: I 100% agree with @Morteza. I wrote it yesterday to your question about converting ICollection to EntityCollection but I deleted it later - if you use POCO don't work with EntityCollection at all. You are corrupting your architecture. Initializing collections is pattern in POCO - check what is generated by POCO T4 template. The code previously posted by @StackOverflowException (only 10k+ rep. users can see it now) was fully valid answer to your question. – Ladislav Mrnka Feb 18 '11 at 09:11
  • Ok, it appears I am fighting an uphill battle just to be able to perform integration tests to determine if a collection has been eager loaded or not. Thanks guys. – KallDrexx Feb 18 '11 at 13:03