1

My DAL is based on Entity Framework Code First.

I have a post model and a tag model. One post can have several posts attached.

Here is my post:

public class Post 
{
    [Key]
    public int PostID { get; set; }
    ...
    public virtual ICollection<Tag> Tags { get; set; }
}

Here is my tag:

public class Tag
{
    [Key]
    public int TagID { get; set; }

    [Required, StringLength(50)]
    public string Name { get; set; }

    public virtual ICollection<Post> Posts { get; set; }
}

When I save my post, I don't have any errors but nothing is saved in the DB.

enter image description here

As you can see on the screenshot above the TagID is 0 and I don't know why???

enter image description here

Any idea? Suggestions?

My tables are correctly created in Sql Server.

Thanks.

PS: My code must be ok because I copy/paste it from another location (where it works).


UPDATE

Here is the code to update tag entities (under a specific post)

    Tag t = m_TagRepository.GetTag(tag.Trim().ToUpper());
    if (t == null) t = new Tag { Name = tag.Trim().ToUpper() };
    post.Tags.Add(t);

Here is the code to save changes to a post (and tag below)

    public void SavePost(Post post)
    {
        if (post.PostID == 0)
        {
            m_Context.Posts.Add(post);
        }
        else
        {
            var entry = m_Context.Entry(post);
            entry.State = EntityState.Modified;
        }            
        m_Context.SaveChanges();
    }

I get the post back from the Edit view page:

    [Authorize, HttpPost, ValidateInput(false), Theme("Admin")]
    public ActionResult Edit(PostFullViewModel postToEdit)
    {
        if (!ModelState.IsValid)
            return View();

        Post post = Mapper.Map<PostFullViewModel, Post>(postToEdit);
        m_PostBusiness.UpdateTags(post, postToEdit.TagString);
        m_PostBusiness.SavePost(post);
        TempData.SetStatusMessage(Strings.Post_SavedSuccessfully);

        return RedirectToAction("Manage");
    }
Bronzato
  • 9,152
  • 21
  • 106
  • 196

2 Answers2

1

It is common problem asked many times. You got your post view model from HTTP request and mapped it to your post entity but the entity was created outside of EF context. You than added some tag to this unattached post, attached the post and change the state of the post to modified.

Now where is the problem? The problem is in EF state model. Each entity and each independent association has its own state. Changing post to modified has only said to EF that post was updated but the tag and relation between tag and post remains unchanged. Because of that EF will save only post.

The simple solution for specific case is doing this:

var post = GetPostFromYourRequest();
context.Posts.Attach(post);
ProcessTags(post, postToEdit);
context.SaveChanges();

The whole complicated logic is in process tags. Here it depends on what you want to do. If you only want to create new tags you will do what you did now (you must load existing tag from database with the same context you used for attaching post).

If you want to do any complex operation you should load original post with all tags from database and merge your incoming view model to original state. For example removing relation between existing post and tags is very hard to do without having current state from database loaded again. Detailed explanation of the problem is here.

Community
  • 1
  • 1
Ladislav Mrnka
  • 349,807
  • 56
  • 643
  • 654
0
  1. Figure out why TagID is 0 - WHen TagID is 0, you don't set the state as modified so nothing is saved.
  2. Fire up the SQL profiler to see what's happening on the SQL side (probably nothing because of 1)
  3. Go through Tom's excellent EF/MVC tutorial
RickAndMSFT
  • 16,022
  • 5
  • 50
  • 66