EF更新实体时,可以对实体对象进行跟踪。
如 方法一
public ActionResult Update(SysAccount account, string returnUrl)
其中account是表单传递过来的对象,对象里属性包含主键ID。
直接AccountServer.UpdateEntity(account);就可以实现更新。
也可以先根据ID查询出实体,再对实体进行修改。
如 方法二
public ActionResult Update(int ID, string returnUrl)
{
Account account=GetEntityByID(ID)
account.Name=Request["accountname"];
AccountServer.UpdateEntity(account);
}
主外键一对一和一对多都能够实现跟踪,然后自动绑定外键和关联的模型主键。
但是今天account和role是多对多关系。
下面Update方法的代码account的其他属性都能得到更新,而且没有报错。
只有account.Companies没有更新
断点看了一下account.Companies有值且正确,只是没有保存更新
ISysAccount.UpdateEntity更新方法的主要代码如下
public virtual T UpdateEntity(T entity)
{
if (entity != null)
{
context.Set<T>().Attach(entity);
context.Entry(entity).State = EntityState.Modified;
context.SaveChanges();
}
return entity;
}
现在用的方法二,先查询一次,对查询结果进行修改。相对于方法一,多了一次查询。
之前一对多的跟踪是没问题的,执行DbContext的SaveChange后,导航属性外键会于其对应的实体相关联。
现在多对多的关联关系的修改为什么没有保存。
奇怪的是,AddEntity(account)时,也就是包含多对多关系的实体在创建时,关联的实体关系是能保存的。add主要代码如下
public virtual T AddEntity(T entity)
{
context.Set<T>().Add(entity);
context.SaveChanges();
return entity;
}
采用FluntAPI绑定多对多关系
this.HasMany(u => u.Companies)
.WithMany(u => u.Accounts)
.Map(m =>
{
m.ToTable("AccountCompany");
m.MapLeftKey("AccountId");
m.MapRightKey("CompanyId");
});
下面是更新实体的Update方法
[HttpPost]
public ActionResult Update(SysAccount account, string returnUrl)
{
if (ModelState.IsValid)
{
////添加用户的公司
var companyIds = Request["CompanyId"];
if (!string.IsNullOrEmpty(companyIds))
{
List<int> companyIdsList = companyIds.Split(',').Select(Int32.Parse).ToList();
//新的公司
var companiesList = ISysCompany.LoadEntities(c => c.EnabledMark == true).Where(c => companyIdsList.Contains(c.Id)).ToList();
foreach (var company in companiesList)
{
account.Companies.Add(company);
}
}
else
{
account.Companies.Clear();
}
if (ISysAccount.UpdateEntity(account) != null)
{
if (String.IsNullOrEmpty(returnUrl))
return RedirectToAction("List", "Account");
else
return Redirect(returnUrl);
}
else
{
ModelState.AddModelError("", "修改失败");
}
}
else
{
ModelState.AddModelError("", "请填写完整");
}
List<SelectListItem> enabledMark = new List<SelectListItem>() { new SelectListItem() { Value = "0", Text = "删除" }, new SelectListItem() { Value = "1", Text = "正常" } };
ViewBag.EnabledMark = new SelectList(enabledMark, "Value", "Text", account.EnabledMark);
return View(account);
}
4 个解决方案
#1
提问有点仓促,语言组织的有点差,希望大家不要介意。
#2
还是喜欢dbfirst,数据库结构设计的事情让数据库自己来保证,出问题也是dba的事,何况数据库可能还是第三方的
#3
看看增加以下[InverseProperty("")] 属性能否解决这个问题
http://blog.csdn.net/hanjun0612/article/details/52838692
http://blog.csdn.net/hanjun0612/article/details/52838692
#4
多谢!
#1
提问有点仓促,语言组织的有点差,希望大家不要介意。
#2
还是喜欢dbfirst,数据库结构设计的事情让数据库自己来保证,出问题也是dba的事,何况数据库可能还是第三方的
#3
看看增加以下[InverseProperty("")] 属性能否解决这个问题
http://blog.csdn.net/hanjun0612/article/details/52838692
http://blog.csdn.net/hanjun0612/article/details/52838692
#4
多谢!