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

Entity framework EF4 CTP5 POCO未在保存时更新导航属性,entity-framework,poco,Entity Framework,Poco,我将EF4与POCO对象一起使用,这两个表如下 服务 服务ID, 名称 状态ID 状态 状态ID, 名字 POCO对象如下所示 public static void SaveService(Service service) { using (var ctx = Context.CreateContext()) { ctx.AttachModify("Services", service); ctx.AttachTo("Statuses",servi

我将EF4与POCO对象一起使用,这两个表如下

服务 服务ID, 名称 状态ID

状态 状态ID, 名字

POCO对象如下所示

public static void SaveService(Service service)
{
    using (var ctx = Context.CreateContext())
    {
        ctx.AttachModify("Services", service);
        ctx.AttachTo("Statuses",service.Status);
        ctx.SaveChanges();
    }
}
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);
}
服务 服务ID, 地位 名字

状态 状态ID, 名字

服务对象上的状态为导航属性且类型为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();
    }
}
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);
}
AttachModify方法将对象附加到上下文并将其设置为modified,如下所示

public static void SaveService(Service service)
{
    using (var ctx = Context.CreateContext())
    {
        ctx.AttachModify("Services", service);
        ctx.AttachTo("Statuses",service.Status);
        ctx.SaveChanges();
    }
}
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中使用。

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

这个问题一直拖下去,所以我最终选择了一个我不太满意的解决方案,但我只需要让它工作起来

我的解决方案是在保存时从数据库中重新获取实体,并使用ApplyCurrentValue更新它们以匹配更新的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();
    }
}

我真的希望它按照问题中的编码方式工作,因为我认为这是一个更简洁的解决方案,因此,如果有人可以在这方面进行改进,请执行

您是否也尝试过执行
ctx.AttachModify(“Status”,service.Status)?是的,我试过了,它也不起作用。这是一篇很好的博客文章,其中包含一些示例代码,我已经将状态设置为“修改”,并尝试使用“附加”而不是“附加到”,但没有成功。