Nikita
Nikita

Reputation: 1082

How to save item with navigation property to DB Entity Framework 6

public void Add(Site obj)
{
    if(obj.Id == 0 || obj.Id >= 10000)
    {
        context.Sites.Add(obj);
    } else
    {
        Site dbEntry = context.Sites.Find(obj.Id);
        if (dbEntry != null)
        {
             ...
        }
    }
    context.SaveChanges();
    return res;
}

class Site {
  public virtual List<Page> Pages { get; set; }
}

class Page {
    public virtual Site Site {get;set;}
}

In Add method Obj.Pages.Site(foreach of pages) is null, but Site.Pages not, I expected that when I save to DB Site A Site.Pages will be saved to DB too,and for each Page navigation property Site will be set to A. Pages are saving, but Site_Id in db is null. Should I create my own foreign keys or there is possibility to use entity-framework keys?

Upvotes: 0

Views: 1914

Answers (2)

Nikita
Nikita

Reputation: 1082

This code is valid. To find out the problem I've done the next:

1)add public int FieldId for each nav property
2)drop and recreate database
3)int is not nullable by default so now when try to add new record EF throws exception

In other words I make EF throws exception if it can't set navigation property, it helps me to find the error in my code(just set break point before crash and debug step by step). By default if it is not possible to set a navigation property EF set it to NULL

Upvotes: 0

Luis Lavieri
Luis Lavieri

Reputation: 4129

Move your SaveChanges() to the if statement after you add the site. Basically, You have to Save the changes and commit the transaction before being able to access all your navigation properties. Commiting the transaction using context.Database.BeginTransaction() is optional, so you are able to rollback in the case of a problem. But the savechanges has to be before trying to access the navigation properties. Try to separate the code into functions so it is easier to read. An example would be like this:

public void Add(Site obj)
{
    using(var context = new SiteContext())
    {
        using(var dbContextTransaction = new context.Database.BeginTransaction())
        {
            try
            {
                context.Sites.Add(obj);
                context.Entry(obj).State = obj.Id == 0 ? EntityState.Added : EntityState.Modified;
                context.SaveChanges();
                dbContextTransaction.Commit();
            }
            catch (Exception ex)
            {
                dbContextTransaction.Rollback();
                throw;
            }
        }
    }
}

Then, if you want to get the same entry you should do something like

public Site GetSiteById(int id)
{
    using(var context = new SiteContext())
    {
        return context.Sites.FirstOrDefault(i => i.Id == id);
    }
}

But, the context has to save changes and commit the transaction first. Then, you will have all your properties filled.

Upvotes: 1

Related Questions