C# 高效、雄辩地插入/删除/更新子记录

C# 高效、雄辩地插入/删除/更新子记录,c#,asp.net,asp.net-mvc,entity-framework,ef-code-first,C#,Asp.net,Asp.net Mvc,Entity Framework,Ef Code First,我有一个页面,显示了标题记录和详细记录列表。当用户单击“保存”时,我正在努力创建一种干净高效的方法来插入/删除/更新详细记录 详细记录显示在jQuery数据表中,每个详细记录后面的视图模型都有一个IsNew和IsRemoved属性。当用户添加详细信息记录时,其IsNew属性设置为true。当用户删除详细信息记录时,该记录将被软删除,其IsRemoved属性设置为true 当用户单击Save并将页面发布到我的控制器时,我现在的逻辑如下所示 [HttpPost] public ActionResul

我有一个页面,显示了标题记录和详细记录列表。当用户单击“保存”时,我正在努力创建一种干净高效的方法来插入/删除/更新详细记录

详细记录显示在jQuery数据表中,每个详细记录后面的视图模型都有一个IsNew和IsRemoved属性。当用户添加详细信息记录时,其IsNew属性设置为true。当用户删除详细信息记录时,该记录将被软删除,其IsRemoved属性设置为true

当用户单击Save并将页面发布到我的控制器时,我现在的逻辑如下所示

[HttpPost]
public ActionResult EditData(ViewModel viewModel)
{
    // Update the record's header details here
    // ...

    foreach (var childViewModel in viewModel.Children)
    {
        // Use AutoMapper to map the view model to a model
        MyChildRecord childModel = this.mapper.Map<MyChildRecord>(childViewModel);

        if (childViewModel.IsNew)
        {
            this.context.MyChildRecords.Add(childModel);                
        }
        else if (childViewModel.IsRemoved)
        {
            this.context.MyChildRecords.Attach(childModel);
            this.context.MyChildRecords.Remove(childModel);
        }
        else
        {
            this.context.Entry(childModel).State = EntityState.Modified;
        }
    }

    this.context.SaveChanges();

    return RedirectToAction("EditData", new { id = viewModel.Id } );
}
[HttpPost]
公共操作结果编辑数据(ViewModel ViewModel)
{
//在此处更新记录的标题详细信息
// ...
foreach(viewModel.Children中的var childViewModel)
{
//使用AutoMapper将视图模型映射到模型
MyChildRecord childModel=this.mapper.Map(childViewModel);
if(childViewModel.IsNew)
{
this.context.MyChildRecords.Add(childModel);
}
else if(childViewModel.IsRemoved)
{
this.context.MyChildRecords.Attach(childModel);
this.context.MyChildRecords.Remove(childModel);
}
其他的
{
this.context.Entry(childModel.State=EntityState.Modified;
}
}
this.context.SaveChanges();
返回RedirectToAction(“EditData”,新的{id=viewModel.id});
}
我不喜欢这段代码的一点是,即使子记录没有任何更改,我仍然在数据库中更新它。我能想出的防止这种情况发生的唯一办法是

  • 让每个视图模型存储其原始值的副本,然后在用户保存页面时将其当前值与其原始值进行比较。我不喜欢这个解决方案,因为我需要一堆代码来存储原始值,然后我必须将原始值作为隐藏字段放在我的ASP页面上,以便它们在web请求之间传递

  • 当用户保存页面时,让控制器遍历每个子视图模型,从数据库加载原始数据,并比较视图模型的当前值,以查看行是否需要更新。我不喜欢这种方法,因为它需要很多额外的代码来进行字段比较,而且我仍然需要对数据库进行不必要的访问


  • 这似乎是一种常见的情况,因此必须有一种普遍接受的方法来做到这一点。首先,考虑到额外的更新是否会带来额外的网络流量,很可能是你的实际数据库服务器足够聪明,如果没有发生变化,就不会对磁盘上的数据库做任何事情。p>

    第二,考虑您的应用程序可能不是唯一与数据库表一起工作的程序。当你查看记录时,其他人可能已经更改了记录。为了安全起见,您确实需要将这两种解决方案结合在一起:检查用户是否更改了表单,以及检查数据库行是否与您获得要向用户显示的数据时相同。如果两者都发生了更改,通常会将其视为错误并通知用户。

    您建议我如何进行逐字段比较?我担心,随着应用程序的增长,编写每个字段的比较会非常耗时,而且在将其他字段添加到预先存在的类中时也会很容易出现错误,因为程序员可能会忘记将它们添加到比较方法中,或者忘了将它们作为隐藏字段添加到ASP页面中。我可以通过使用反射创建比较函数来解决手动比较问题,但ASP隐藏字段问题仍然存在。如果这是唯一的办法,那就这样吧;我只是希望有更好的解决方案。在数据库方面,通常的解决方案是使用ORM框架,如NHibernate、LINQ to SQL或Microsoft的Entity framework或类似的框架,而不是直接使用SQL。这样的框架将在编译时自动生成大量而枯燥的检查代码。我不太喜欢UI方面,但我相信MVC(Model View Controller)有相关的概念,可以检测回发时哪些字段发生了更改。实际上,归根结底,你自己做的太多了。了解并使用行业标准解决方案。我正在使用Entity Framework,但我不确定这是如何解决将所有视图模型字段与模型字段进行比较的问题,还是如何解决页面上有一堆隐藏的ASP字段的问题。我是否还需要做一系列检查,比如
    if(viewModel.FirstName!=model.FirstName | | viewModel.LastName!=model.LastName | | |……
    我想我对你的问题的理解力都很差,我很抱歉。也许我应该删除这个答案;你肯定应该取消投票,因为它没有回答你。