开发者

EF4 CTP5 POCO Not Updating Navigation Property On Save

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 开发者_JS百科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

static void Main(string[] args)
{
    Service svc = GetService();
    svc.Status = GetStatus("Stopped");
    using (var ctx = new TestEFContext())
    {
        var svc2 = ctx.Services.Where(s=>s.ServiceID == svc.ServiceID).FirstOrDefault();
        svc2.Status = ctx.Statuses.Where(n => n.StatusID == svc.Status.StatusID).FirstOrDefault();
        ctx.ApplyCurrentValues("Services", svc);                                
        ctx.SaveChanges();
    }
}

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


You must manually set state to Modified for each entity you want to update. Attaching entity to context set its state to Unchanged. Also you don't need to attach status separately. It is already attached with service because AttachTo method attaches whole object graph. You can also try to use Attach instead of AttachTo but I don't think it will be source of the problem.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜