代码首先没有更新子对象
本文关键字:更新 对象 代码 | 更新日期: 2023-09-27 17:49:37
我在用CodeFirst更新POCO的子对象时遇到问题。我的POCO如下
public class Place
{
public int ID { get; set;
public string Name { get; set; }
public virtual Address Address { get; set; }
}
public class Address
{
public int ID { get; set;
public string AddressLine { get; set; }
public string City { get; set; }
public virtual State State { get; set; }
}
public class State
{
public int ID { get; set;
public string Name { get; set; }
}
我有一个视图来编辑所有字段的地方和它的孩子。所有属性都是文本框,除了State是一个下拉列表。
当用户单击保存按钮时,视图返回所有填充的Place属性,除了State,它只填充ID,因为它的值来自下拉列表,Name为空。
在Edit Post Method中,我有以下代码:
if (ModelState.IsValid)
{
bool isNewPlace = place.ID == -1;
//Hack, State name is empty from View, we reload
place.Address.State = new StateBLL().GetByID(place.Address.State.ID);
new PlaceBLL().Update(place);
return RedirectToAction("Index");
}
和PlaceBLL类的更新代码如下
protected override void Update(Place place)
{
MyDbContext.Instance().Set<Address>().Attach(place.Address);
MyDbContext.Instance().Entry(place.Address).State = System.Data.EntityState.Modified;
MyDbContext.Instance().Set<State>().Attach(place.Address.State);
MyDbContext.Instance().Entry(place.Address.State) = System.Data.EntityState.Modified;
MyDbContext.Instance().SaveChanges();
}
当用户编辑Place对象的所有字段都正确更新,除了状态,当用户改变一些地方的状态时,这种变化不会持久化到数据库中,似乎Code首先没有检测到用户的状态变化。
你知道为什么代码首先不能从Place检测状态更改值吗?
谢谢。
您的Update
方法更新了Address
的(标量属性),并更新了State
的(标量属性),但它不更新place
和Address
之间的关系(这不是问题,因为您显然只在视图中编辑Address
属性,而不将另一个Address
实体分配给place
),它不更新place.Address
和place.Address.State
之间的关系。但这是你在视图中实际改变的内容。
要更新place.Address
和place.Address.State
之间的关系,您有两个选项:
-
在
Address
类中引入一个外键属性,该属性表示对状态的FK(这种类型的关联称为外键关联):public class Address { public int ID { get; set; public string AddressLine { get; set; } public string City { get; set; } public int StateID { get; set; } public virtual State State { get; set; } }
然后确保将下拉列表绑定到
place.Address.StateID
(而不是place.Address.State.ID
)。当您将视图发布到服务器时,FK属性StateID
将使用从下拉列表中选择的新ID填充。在你的Update
方法中,你可以删除第三和第四行。单独更新Address
也会更新StateID
外键。您还可以在编辑后操作中删除加载State
的代码。 -
如果您想保持当前的独立关联(=在您的模型类中没有暴露外键属性的关联),您必须从数据库中加载原始状态并使用新状态更新它:
protected override void Update(Place place) { var dbPlace = MyDbContext.Instance().Places.Include(p => p.Address.State) .Single(p => p.ID == place.ID); // Update scalar properties of place MyDbContext.Instance().Entry(dbPlace) .CurrentValues.SetValues(place); // Update scalar properties of Address MyDbContext.Instance().Entry(dbPlace.Address) .CurrentValues.SetValues(place.Address); // Change relationship between Adress and State if (dbPlace.Address.State.ID != place.Address.State.ID) { MyDbContext.Instance().States.Attach(place.Address.State); dbPlace.Address.State = place.Address.State; } MyDbContext.Instance().SaveChanges(); }
同样,您可以在Edit Post操作中删除加载
State
的代码,因为正确的密钥属性(State.ID
)足以改变关系。
您还需要附加实体。下面是你需要做的一个简单版本。
var updated = _dbSet.Attach(item);
_dataContext.Entry(item).State = EntityState.Modified;
return updated;