可能重复:
Delete object and all its child objects in Entity Framework?
此代码:
int WebsiteID = int.Parse(Request.QueryString["id"]);
Website websiteObj = db.Websites
.SingleOrDefault(x => x.website_id == WebsiteID);
foreach (BusinessObjects.Page pageObj in websiteObj.Pages)
{
foreach (SubPage subpageObj in pageObj.SubPages)
{
pageObj.SubPages.Remove(subpageObj);
}
websiteObj.Pages.Remove(pageObj);
}
foreach (Sector sectorObj in websiteObj.Sectors)
{
foreach (Product productObj in sectorObj.Products)
{
sectorObj.Products.Remove(productObj);
}
websiteObj.Sectors.Remove(sectorObj);
}
db.Websites.DeleteObject(websiteObj);
网站有多个页面,一个页面有多个子页面。一个网站也有多个部门,每个部门都有多个产品。
我想删除该网站并清除与其相关的所有关系+实体。我确信有更好的方法来编写上述内容。
有没有办法改善逻辑?
答案 0 :(得分:4)
最简单的方法是将数据库中的关系设置为ON DELETE CASCADE
然后Linq成为:
var sites = db.Websites;
var site_id = int.Parse(Request.QueryString["id"]);
var site = sites.FirstOrDefault(x => x.website_id == site_id);
sites.DeleteObject(site);
除了删除级联之外,我对你的linq所做的唯一真正的改变除了删除不再需要的内容:
使用FirstOrDefault
获得轻微的性能提升。这对数据库来说并不算太大,因为它只需要TOP 2
来实现。当Single
起作用时,不值得First
,因为在其他情况下,它可能意味着必须检查每个单独的对象(仅Single
对List<T>
)*的方式。当然,如果有两个网站具有相同ID的可能性,那么我刚刚介绍了一个错误,但真正的错误是没有将id作为主键来确保永远不会发生这种情况。 / p>
从对象名称中取出Obj
。这似乎是“对象”的缩写,因此是同义的 - 所有编写的.NET代码中的每个其他变量都是针对一个对象的,所以没有必要指出这一点。
*对此更多一点,因为我不想鼓励坏习惯。当只有一个匹配对象时,First
获取该对象,而Single
获取该对象,也确保它是唯一的一个(同样适用于{ {1}}变体除了它们在根本没有找到对象时有所不同。
知道只有一个匹配对象的唯一方法是尝试找到至少两个匹配对象,然后检查你只有一个。如果数据库表在与您的搜索相关的列上建立索引(它是OrDefault
而不是TOP 2
),则对数据库表的影响很小,但是否则会很严重。
问题是这项检查的重要性。有时你不在乎;使用TOP 1
。有时你应该有一种强烈的信心,即只有一个这样的对象;使用First
但请检查信心的原因以确保您没有错误(在这种情况下,请检查索引列上是否有主键或唯一键)。如果您确实需要检查,那么请使用First
,因为在这种情况下使用Single
是错误优化的一个缩影 - 更快但错误绝不是目标。