我正在使用带有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中以断开连接的方式使用它。
答案 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
,但我认为这不会成为问题的根源。