EF4 CTP5 POCO未保存时更新导航属性

时间:2011-01-05 09:48:11

标签: entity-framework poco

我正在使用带有POCO对象的EF4,2个表格如下

服务 服务ID, 名称, StatusID

状态 StatusID, 名称

POCO对象看起来像这样

服务 服务ID, 状态, 名称

状态 StatusID, 名称

Service对象上的Status是导航属性,类型为Status。

在我的服务存储库中,我有一个save方法,它将服务对象附加到上下文并调用save。这适用于服务,但如果该服务的状态已更改,则不会更新。我的保存方法看起来像这样

public static void SaveService(Service service)
{
    using (var ctx = Context.CreateContext())
    {
        ctx.AttachModify("Services", service);
        ctx.AttachTo("Statuses",service.Status);
        ctx.SaveChanges();
    }
}

AttachModify方法将对象附加到上下文并将其设置为已修改,如下所示

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);
}

如果我查看一个SQL配置文件,它甚至不包括服务表更新中的导航属性,它永远不会触及StatusID。这让我疯狂。知道我需要做什么来强制导航属性更新吗?

修改

举一个问题的快速示例,这是一个快速的控制台应用程序,它使用EF和我的POCO对象来产生这个问题

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; }
}

我没有坚持上下文的原因是因为在真正的应用程序中我试图在WCF中以断开连接的方式使用它。

2 个答案:

答案 0 :(得分:2)

这个问题拖延了所以我最终找到了一个解决方案,我并不满意,但我只是需要让它运转起来。

我的解决方案是保存以从数据库重新获取实体并使用ApplyCurrentValues更新它们以匹配更新的POCO对象。

根据我在问题中的示例,这是我使用的解决方案

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();
    }
}

我真的宁愿让它按照问题编码的方式工作,因为我认为这是一个更简洁的解决方案,所以如果有人可以改进,请做

答案 1 :(得分:0)

您必须为要更新的每个实体手动将状态设置为Modified。将实体附加到上下文将其状态设置为Unchanged。此外,您无需单独附加状态。它已附加服务,因为AttachTo方法附加了整个对象图。您也可以尝试使用Attach代替AttachTo,但我认为这不会成为问题的根源。