I’m using EF4 with POCO objects the 2 tables are as follows
Service
ServiceID,
Name,
StatusID
Status
StatusID,
Name
The POCO objects look like this
Service
ServiceID,
Status,
Name
Status
StatusID,
Name
With Status on the Service object being a Navigation Property and of type Status.
In my Service Repository I have a save method that takes a service objects attaches it to the context and calls save. This works fine for the service, but if the status for that service has been changed it does not get updated. My Save method looks like this
public static void SaveService(Service service)
{
using (var ctx = Context.CreateContext())
{
ctx.AttachModify("Services", service);
ctx.AttachTo("Statuses",service.Status);
ctx.SaveChanges();
}
}
The AttachModify method attaches an object to the context and sets it to modified it looks like this
public void AttachModify(string entitySetName, object entity)
{
if (entity != null)
{
AttachTo(entitySetName, entity);
SetModified(entity);
}
}
public void SetModified(object entity)
{
ObjectStateManager.ChangeObjectState(entity, EntityState.Modified);
}
If I look at a SQL profile its not even including the navigation property in the update for the service table, it never touches the StatusID. Its driving me crazy. Any idea what I need to do to force the Navigation Property to update?
Edit
To give a quick example of the problem heres a quick console app that uses EF with my POCO objects to produce this issue
static void Main(string[] args)
{
Service svc = GetService();
Console.WriteLine("Service : " + svc.Name + " , Status : " + svc.Status.Name);
//Change and save Status
svc.Status = GetStatus("Stopped");
using (var ctx = new TestEFContext())
{
//Status is changed
Console.WriteLine("Service : " + svc.Name + " , Status : " + svc.Status.Name);
ctx.AttachModify("Services", svc);
ctx.AttachTo("Statuses", svc.Status);
ctx.SaveChanges();
}
//Re-fetch service from db and check status
svc = GetService();
//Status is set back to its old value!!!!!!!!
Console.WriteLine("Service : " + svc.Name + " , Status : " + svc.Status.Name);
Console.ReadLine();
}
private static Service GetService()
{
using (var ctx = new TestEFContext())
{
return ctx.Services.Include("Status").FirstOrDefault();
}
}
private static Status GetStatus(string name)
{
using (var ctx = new TestEFContext())
{
return ctx.Statuses.Where(n=>n.Name == name).FirstOrDefault();
}
}
public class Service
{
[DataMember] public int ServiceID { get; set; }
[DataMember] public string Name { get; set; }
[DataMember] public Status Status { get; set; }
}
public class Status
{
[DataMember] public int StatusID { get; set; }
[DataMember] public string Name { get; set; }
}
The reason I’m not holding on to the context is because in the real app I’m trying to use this on its all done in WCF in a disconnected way.
This problem was dragging on so I ended up going for a solution I’m not overlly happy with but I just needed to get it working.
My solution was on save to re-fetch the entities from the DB and use ApplyCurrentValues to update them to match the updated POCO objects.
Based on my example in the question this is the solution I used
I really would rather get it working the way it was coded in the question as I think that is a much neater solution so if anyone can improve on this please do