不,你不能……正常情况下。
多对多关系(具有隐藏的联结表)只能通过在嵌套集合中添加/删除项目来影响。为此,必须加载集合。
但还有一些选择。
选项1。
通过原始 SQL 从联结表中删除数据。基本上这看起来像
context.Database.ExecuteSqlCommand(
"DELETE FROM WebsiteWebsitePage WHERE WebsiteID = x AND WebsitePageID = y"));
(不使用参数)。
选项 2。
将联结包含到类模型中,即将联结表映射到类WebsiteWebsitePage
. Both Website
and WebsitePage
现在将有
public ICollection<WebsiteWebsitePage> WebsiteWebsitePages { get; set; }
and WebsiteWebsitePage
将具有两者的参考属性Website
and WebsitePage
。现在您可以直接通过类模型操作连接点。
我认为这是最好的选择,因为一切都以与具有验证和跟踪等功能的实体合作的标准方式发生。此外,您迟早可能需要一个显式联结类,因为您需要向其中添加更多数据。
选项 3。
技巧之盒。
我尝试通过删除来做到这一点存根实体从集合中。在你的情况下:创建一个WebsitePage
具有有效主键值的对象并将其从中删除Website.WebsitePages
无需加载集合。但 EF 没有注意到更改,因为它没有跟踪Website.WebsitePages
,并且该项目一开始就不在集合中。
但这让我意识到我必须让 EF 轨道成为Website.WebsitePages
包含 1 个项目的集合,然后删除该项目。我首先构建了这个工作Website
项目,然后将其附加到新的上下文。我将展示我使用的代码(标准Product
- Category
模型)以防止拼写错误。
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
已解决。
我对这里发生的情况的解释是:在第二步中,EF 不仅在您附加产品时开始跟踪产品,而且还开始跟踪它的关联,因为它“知道”您无法自己以多对多关系加载这些关联。但是,当您在第一步中添加类别时,它不会执行此操作。