Asp.net mvc 4 首先使用ef代码更新复杂类型
我有一个名为account的复杂类型,它包含一个许可证列表。 许可证又包含一个域列表(域是一个简单的id+url字符串) 在我的存储库中,我有以下代码Asp.net mvc 4 首先使用ef代码更新复杂类型,asp.net-mvc-4,ef-code-first,entity-framework-5,complextype,Asp.net Mvc 4,Ef Code First,Entity Framework 5,Complextype,我有一个名为account的复杂类型,它包含一个许可证列表。 许可证又包含一个域列表(域是一个简单的id+url字符串) 在我的存储库中,我有以下代码 public void SaveLicense(int accountId, License item) { Account account = GetById(accountId); if (account == null) { return;
public void SaveLicense(int accountId, License item)
{
Account account = GetById(accountId);
if (account == null)
{
return;
}
if (item.Id == 0)
{
account.Licenses.Add(item);
}
else
{
ActiveContext.Entry(item).State = EntityState.Modified;
}
ActiveContext.SaveChanges();
}
当我尝试保存更新的许可证(使用修改过的域)时,发生的情况是直接属于许可证的字符串得到了很好的更新
但是没有域得到更新
我应该提到,我所做的是允许用户在用户界面中添加和删除域。任何新域的id为0,任何已删除的域都不在列表中 所以我想要的是
我玩了一点,但没有成功,但我有一个鬼鬼祟祟的怀疑,我在大局中做错了什么,所以如果我误解了一些设计方面的东西,或者只是错过了一些东西,我会喜欢一些提示。这应该足够做你想做的事情了。如果您对代码有更多问题,请告诉我
public void SaveLicense(License item)
{
if (account == null)
{
context.Licenses.Add(item);
}
else if (item.Id > 0)
{
var currentItem = context.Licenses
.Single(t => t.Id == item.Id);
context.Entry(currentItem ).CurrentValues.SetValues(item);
}
ActiveContext.SaveChanges();
}
不幸的是,更新对象图(具有其他相关实体的实体)是一项相当困难的任务,并且实体框架并没有提供非常复杂的支持来简化 问题在于,将实体的状态设置为
Modified
(或通常设置为任何其他状态)只会影响传递到DbContext.Entry
的实体,并且只影响其标量属性。它对其导航属性和相关实体没有影响
您必须手动处理此对象图更新,方法是加载当前存储在数据库中的实体(包括相关实体),并将您在UI中所做的所有更改合并到原始图形中。您的else
案例可能会如下所示:
//...
else
{
var licenseInDb = ActiveContext.Licenses.Include(l => l.Domains)
.SingleOrDefault(l => l.Id == item.Id)
if (licenseInDb != null)
{
// Update the license (only its scalar properties)
ActiveContext.Entry(licenseInDb).CurrentValus.SetValues(item);
// Delete domains from DB that have been deleted in UI
foreach (var domainInDb in licenseInDb.Domains.ToList())
if (!item.Domains.Any(d => d.Id == domainInDb.Id))
ActiveContext.Domains.Remove(domainInDb);
foreach (var domain in item.Domains)
{
var domainInDb = licenseInDb.Domains
.SingleOrDefault(d => d.Id == domain.Id);
if (domainInDb != null)
// Update existing domains
ActiveContext.Entry(domainInDb).CurrentValus.SetValues(domain);
else
// Insert new domains
licenseInDb.Domains.Add(domain);
}
}
}
ActiveContext.SaveChanges();
//...
您还可以尝试以通用方式对任意分离的对象图执行这项工作
另一种方法是跟踪UI层中某些自定义字段中的所有更改,然后在数据发回时评估跟踪的状态更改,以设置适当的实体状态。由于您在web应用程序中,这基本上意味着您必须在用户更改值、添加新项目或删除项目时跟踪浏览器中的更改(很可能需要一些Javascript)。在我看来,这个解决方案甚至更难实施。谢谢,正如我所担心的那样,但至少我现在已经确认了,并且没有因为不得不这样做而感到如此不安。。。如果是这样的话:-)但是如果他们能够在EF@RickardLiljeberg:是的,您可以使用上面的代码,但这只是一个子集合。如果你有多个收藏品和孙子孙女,那就不好笑了。。。顺便说一句:您可以投票支持以下功能:。但这不会发生在EF 7之前(如果有的话),所以可能至少要等一年。我很高兴地投了票,事实上我很惊讶地发现EF在这方面是多么有限。这听起来像个笑话。这个答案确实让我在第一步就质疑了我对EntityFramework和nhibernate的选择——我们还有一段合理的发布时间,我正在考虑转换。