【问题标题】:Removing Related Objects from Database with Entity Framework使用实体框架从数据库中删除相关对象
【发布时间】:2017-08-31 05:12:19
【问题描述】:

这是我在这个网站上的第一个问题。我在 ASP.Net Web 应用程序中自学 MVC 和实体框架。我有一系列相关实体,当我调用 context.saveChanges() 时,已删除的相关数据项不会被删除。

我的实体 我有一个可以有 0 到多个别名的项目实体。这是数据库第一个项目,其中大部分代码行都是自动生成的。

public Class Item
{
  public int Id{get;set};
  public string Name {get;set;}
  public virtual ICollection<AliasClass> AssociatedAliases {get;set;}
}

public Class AliasClass
{
  public int Id {get;set;}
  public int ItemId {get;set;}
  public string AliasName {get;set;}

  public virtual Item RelatedItem {get;set;}
}

好的,我们已经完成了自动生成的内容。我的回发操作接受回发视图模型。我正在实施存储库模式。我的 Item Repo 有更新功能。

[HttpPost]
public ActionResult Edit (Models.EditViewPostBack MyPostBackModel)
{
  If (!ModelState.isValid){
    ... rebuild and copy  // this part works. Skipping over it
  }

  // this may be a key line of my issue
  MyPostBackModel.Item.Alias = MyPostBackModel.myAliases;
  ItemRepo.Update(MyPostBackModel.Item);
  return RedirectToAction("Index","Home");
}

这里是 Models.EditViewPostBack。新的关联列表作为数组传回。新关联的 id 为 0。在更新时,它将被分配一个真实的 Id。

    public class EditViewPostBack{
      Item myItem {get; set;}
      AliasClass[] myAliases {get;set;}
    }

现在,终于到了项目的核心和我真正的问题。这是 ItemRepo 中应该更新更改的方法。

    public void Update (Item myItem)
    {

      // myItem.AssociatedAliases contains only the wanted associations. 
      // It doesn't have the to-be deleted items. 
      // new items have an id of 0

      // defined in class constructor. 
      context.Item.Attach(myItem);
      context.Entry(Item).State = EntityState.Modified;
      foreach(var name in myItem.AssociatedAliases){
        // finds the modified local version of the item. doesn't connect
        // to the database to location info.
        if(name.id > 0)
        {
          var moded = context.AliasClass.find(name.Id); 
          context.Entry(moded).State = EntityState.Modified;
        }
        else
        {
          // it is brand new
          context.Item.Add(name)
        }
      }          
      //
      // Once the alias is not attached to it's item it has to go
      // How to handle deletes goes here
      //
      context.SaveChanges();
    }

因为实体状态没有被标记为已删除,所以关联仍然存在,并且该项目看起来就像我从未删除它一样。我已经尝试了几件事。

如果我使用 context.Alias.linqFunction() 加载或搜索原始项目,则由于 id 匹配,整个列表将与 myItem 参数重新关联。

// invoking the following line causes Item.Alias to fully re-associate.
// I lose the list passed to the function 
context.AliasClass.Where(x=>x.ItemId == myItem.Id)

我目前无法加载别名,因为这将是到我不删除项目的数据库的往返。

我认为我需要一种删除方法,除非 Id 与仍然连接的列表匹配。但是 remove 需要一个要删除的项目的实例。

如何从我的数据库中删除这些关联的别名?

【问题讨论】:

    标签: c# asp.net-mvc entity-framework


    【解决方案1】:

    您的问题是因为Aliases 有三种情况 .它们可能是新的和/或编辑或混合的。因此,对于处理,您首先需要处理 Aliases 的更改,而不是 Item 为此创建新的 Alias[],然后执行以下操作:

        foreach(var name in myItem.Aliases){
                 if it is edited one: update it
                 if it is new one: save it with id of myItem
                 }
    

    那么在更新myItem之前,放:

        myItem.Aliases=null;
    

    如果您删除了一些Aliases,则不能指望 EF 不优雅来处理删除它们,就像添加新的一样。您需要自己删除它们。 所以应该有类似

    allAliases=context.Getall(Aliases).where(they are for current item);
    

    那么你可以拥有

    foreach(var aliase in allAliases){
             if it it isnot in myItem.Aliases: delete it
             }
    

    为了更好的性能和更少的复杂性,我建议你先删除数据库中的所有Aliases,然后你所有的myItem.Aliases 将作为新的。因此,当您保存 myItem 时,所有相关的 Aliases 都会自动添加,您只需与 db 交互两次,这意味着更好的性能。

    【讨论】:

    • 这不起作用。使 myItem.Aliases 为 null 只会消除与项目的关联,但不会从数据存储中删除它们。我需要不再与项目关联的别名才能删除。现在 Aliases 表中有一个强制性的 ItemId。但是我确实看到了您关于在任何地方使用别名/别名的观点。我将更新我的问题以使用更好的名称以防止混淆。
    • 谢谢你,哈迪。我之前尝试过这样的事情,但遇到了一个问题。您提出的解决方案将始终向数据库发出 2 个请求。这对于更新过程来说似乎非常低效。我之前遇到的问题是,一旦我加载了 itemid 是当前项目的别名,所有以前存在的项目和别名之间的关系都会突然出现在 item.aliasclass 中。所以我会忘记需要添加、删除或更新的内容。
    • 我采纳了您的建议并更改了我的程序以传回应该删除的 ID。我不得不在网站上操作 jquery 并更改保存代码以获取 ID 和空白值。 ID 和值 -> 保存。 ID 和空白 -> 删除。没有 ID 和空白 -> 忽略。没有 ID 值 -> 添加到数据库。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-30
    • 2020-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多