我可以删除,而无需加载整个集合一个孩子的实体?
我有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.