简体   繁体   English

使用实体框架从数据库中删除相关对象

[英]Removing Related Objects from Database with Entity Framework

This is my first question on this site. 这是我在本网站上的第一个问题。 I am teaching myself MVC and Entity Framework in an ASP.Net web app. 我正在ASP.Net Web应用程序中自学MVC和实体框架。 I have a series of related entities and when I call context.saveChanges() the removed related data items do not get removed. 我有一系列相关实体,当我调用context.saveChanges()时,删除的相关数据项不会被删除。

My Entities I have an Item Entity that can have 0 to Many Aliases. 我的实体我有一个项目实体,可以有0到许多别名。 This was database first project and most of these lines of code have been auto generated. 这是数据库的第一个项目,大多数这些代码行都是自动生成的。

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;}
}

Ok, we are done with the autogenerated stuff. 好的,我们完成了自动生成的内容。 My Postback action accepts a postback viewmodel. 我的回发操作接受回发视图模型。 I am implementing repository pattern. 我正在实现存储库模式。 And my Item Repo has an update function. 我的物品回购具有更新功能。

[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");
}

Here is Models.EditViewPostBack. 这是Models.EditViewPostBack。 The new list of associations get passed back as an array. 新的关联列表将作为数组传回。 New associations have an id of 0. At update it will be assigned a real Id. 新关联的ID为0。在更新时,将为其分配一个真实ID。

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

Now, finally the meat of the project and my real issue. 现在,最后是项目的实质,也是我真正的问题。 This is the method from the ItemRepo that is supposed to update changes. 这是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();
    }

Becuase the entitystate isn't marked as deleted the association remains and the item appears like I never removed it. 因为entitystate未被标记为已删除,所以关联仍然存在,并且该项目看起来像我从未删除过。 I have already tried several things. 我已经尝试了几件事。

If i load or search the for the original item with a context.Alias.linqFunction()the entire list is re-associated with the myItem parameter since the id's match. 如果我加载或搜索带有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)

I currently cannot load an Alias because that would be a round trip to the database where I am not deleting the item. 我目前无法加载Alias,因为这将是我未删除该项目的数据库的往返行程。

I think I need a way to Remove except where Id's match the still connected list. 我想我需要一种删除方法,除非Id与仍然连接的列表匹配。 But remove takes an instance of the item to remove. 但是remove需要删除该项目的一个实例。

What can I do to delete these associated Alias names from my database? 我该怎么做才能从数据库中删除这些关联的别名?

Your issue is because of having three situation for Aliases . 您的问题是因为Aliases三种情况。 They maybe are new and or edited or mixed. 它们可能是新的,也可能是经过编辑或混合的。 So for handling that you first need to handle Aliases change separated than Item For doing this create new Alias[] and then do this: 因此,对于处理,您首先需要处理与Item分开的Aliases更改。为此,请创建新的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
             }

Then before updating myItem , just put: 然后在更新myItem之前,只需输入:

    myItem.Aliases=null;

If you have some deleted Aliases , you can't count on EF inelegance to handle deleting them as you so on adding new ones. 如果您有一些已删除的Aliases ,则不能依靠EF优雅来处理删除它们,而只能添加新的Aliases You need to delete them by yourself. 您需要自己删除它们。 So should have something like 所以应该有这样的东西

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

Then you can have 那你可以

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

For better performance and less complexity, I suggest you first delete all Aliases in db and then all your myItem.Aliases will be as new ones. 为了获得更好的性能和更少的复杂性,建议您首先删除db中的所有Aliases ,然后再删除所有myItem.Aliases So when ever you save your myItem all related Aliases will be added automatically and you have just two times interaction with db which means better performance. 因此,无论何时保存myItem所有相关的Aliases都会自动添加,并且与db仅有两次交互,这意味着更好的性能。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM