0
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?

2
  • Are you keeping your context open all the time? Why don't you put in a using? Commented Aug 17, 2016 at 20:19
  • @LuisLavieri There are methods from SiteRepository and PageRepository, context is private field: private SiteContext context = new SiteContext(); Commented Aug 17, 2016 at 20:21

2 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

8 Comments

I don't know about EntityState, if 1) Add obj with existing id 2)set EntityState to Modified 3)SaveChanges - will be these actions update record in db according to obj?
Yes. Because I see that you are checking the Id. To avoid any conflicts with duplicate keys, you need to set the state to modified if its something different than zero. Those Actions will make your Add function better. Because it can save Sites and Update them if required.
I need this check because some objects are generating in json format on client side, their Id start from 10000. Id is a part of markdown and Id should be different, so objects with Id>=10000 I need to add to DB as wel as with Id 0.
Alright. Maybe in the front end you could add a condition that if the id is greater than 10000, set it to zero. But, you understand your requirements better than me. Are you satisfied with my answer or you are still having problems to update the navigation properties?
I've found your answer very usefull, but in my case I do 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 and I've found where I'd made the mistake. After this I've realized that when setting navigation properties if they nullable(as in my question) entity framework in case of exception just set them to Null. I don't like this behaviour and in future I'll always will use both: virtual ClassA Nav; int NavId.
|
0

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

Comments

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.