我可以删除,而无需加载整个集合一个孩子的实体?

问题描述:

我有2个班,像下面。

I have 2 classes, like the below.

他们可以有非常大的集合 - 一个网站可能有2000 + WebsitePages,反之亦然。

They can have very large collections - a Website may have 2,000+ WebsitePages and vice-versa.

  class WebsitePage 
  {
    public int ID {get;set;}
    public string Title {get;set;}
    public List<Website> Websites {get;set;}
  }

  class Website 
  {
    public int ID {get;set;}
    public string Title {get;set;}
    public List<WebsitePage> WebsitePages {get;set;}
  }

我无法从给网站一个WebsitePage。特别是去除复式网站的WebsitePage时。

I am having trouble removing a WebsitePage from a Website. Particularly when removing a WebsitePage from mutliple Websites.

例如,我可能有code是这样的:

For example, I might have code like this:

var pageToRemove = db.WebsitePages.FirstOrDefault();
var websites = db.Websites.Include(i => i.WebsitePages).ToList();
foreach(var website in websites)
{
    website.WebsitePages.Remove(pageToRemove)
}

如果每个网站包括() 2K页,你能想象它需要年龄加载第二行。

If each website Include() 2k pages, you can imagine it takes ages to load that second line.

但是,如果我不包括()的WebsitePages取的网站的时候,有没有孩子收集加载我从删除。

But if I don't Include() the WebsitePages when fetching the Websites, there is no child collection loaded for me to delete from.

我试图刚刚包括(),我需要删除的页面,当然,当储蓄,给我一个空的集合。

I have tried to just Include() the pages that I need to delete, but of course when saving that gives me an empty collection.

有没有解决这个建议或更好的方法?

我与现有的MVC网站工作,我宁可不要为create一个实体类的连接表除非绝对必要。

I am working with an existing MVC site and I would rather not have to create an entity class for the join table unless absolutely necessary.

没有,你不能......正常。

No, you can't... normally.

一个多对多的关系(有隐藏结点表)只能通过添加/删除在嵌套集合物品受到影响。而对于这个集合必须被加载。

A many-to-many relationship (with a hidden junction table) can only be affected by adding/removing items in the nested collections. And for this the collections must be loaded.

但也有一些选择。

从原始的SQL结合表删除数据。基本上,这看起来像

Delete data from the junction table by raw SQL. Basically this looks like

context.Database.ExecuteSqlCommand(
    "DELETE FROM WebsiteWebsitePage WHERE WebsiteID = x AND WebsitePageID = y"));

(不使用参数)。

(not using parameters).

包含交界处到类模型,即结合表映射到一个类 WebsiteWebsitePage 。无论网​​站 WebsitePage 现在将有

Include the junction into the class model, i.e. map the junction table to a class WebsiteWebsitePage. Both Website and WebsitePage will now have

public ICollection<WebsiteWebsitePage> WebsiteWebsitePages { get; set; }

WebsiteWebsitePage 将有参考性既网​​站 WebsitePage 。现在,你可以通过类模型直接操作路口。

and WebsiteWebsitePage will have reference properties to both Website and WebsitePage. Now you can manipulate the junctions directly through the class model.

我认为这是最好的选择,因为一切都发生了与验证和跟踪,所有实体工作的标准方法。此外,有机会,你迟早会需要一个明确的结类,因为你会想要更多的数据添加到它。

I consider this the best option, because everything happens the standard way of working with entities with validations and tracking and all. Also, chances are that sooner or later you will need an explicit junction class because you're going to want to add more data to it.

花样的箱子。

我试图从集合中删除的存根实体的做到这一点。你的情况:创建一个 WebsitePage 对象有一个有效的主键值并从 Website.WebsitePages 而不加载删除采集。但由于它不跟踪 Website.WebsitePages ,并且该项目不在集合中EF不会注意到变化的开始。

I tried to do this by removing a stub entity from the collection. In your case: create a WebsitePage object with a valid primary key value and remove it from Website.WebsitePages without loading the collection. But EF doesn't notice the change because it isn't tracking Website.WebsitePages, and the item is not in the collection to begin with.

但是,这让我意识到我不得不做出EF跟踪 Website.WebsitePages 集合在它1项,然后删除该项目。我首先建立了网​​站项,然后将其连接到新的环境得到了这个工作。我将展示的code我用(标准产品 - 类别模式),以prevent错别字。

But this made me realize I had to make EF track a Website.WebsitePages collection with 1 item in it and then remove that item. I got this working by first building the Website item and then attaching it to a new context. I'll show the code I used (a standard Product - Category model) to prevent typos.

Product prd;

// Step 1: build an object with 1 item in its collection
Category cat = new Category { Id = 3 }; // Stub entity
using(var db = new ProdCatContext())
{
    db.Configuration.LazyLoadingEnabled = false;
    prd = db.Products.First();
    prd.Categories.Add(cat);
}

// Step 2: attach to a new context and remove the category.
using(var db = new ProdCatContext())
{
    db.Configuration.LazyLoadingEnabled = false;
    db.Products.Attach(prd);

    prd.Categories.Remove(cat);

    db.SaveChanges(); // Deletes the junction record.
}

延迟加载被禁用,否则当 prd.Categories 被处理的分类仍然会加载。

Lazy loading is disabled, otherwise the Categories would still be loaded when prd.Categories is addressed.

什么会发生在这里我间pretation是:在第二步中,EF不仅开始跟踪产品时,您可以将它,而且它的关联,因为它知道你自己不能加载这些协会在多对多的关系。它没有做到这一点,但是,当你在第一个步骤中添加的类别。

My interpretation of what happens here is: In the second step, EF not only starts tracking the product when you attach it, but also its associations, because it 'knows' you can't load these associations yourself in a many to many relationship. It doesn't do this, however, when you add the category in the first step.