使用LINQ改进f​​oreach

时间:2012-08-26 10:34:34

标签: c# asp.net linq entity-framework

  

可能重复:
  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);

网站有多个页面,一个页面有多个子页面。一个网站也有多个部门,每个部门都有多个产品。

我想删除该网站并清除与其相关的所有关系+实体。我确信有更好的方法来编写上述内容。

有没有办法改善逻辑?

1 个答案:

答案 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,因为在其他情况下,它可能意味着必须检查每个单独的对象(仅SingleList<T>)*的方式。当然,如果有两个网站具有相同ID的可能性,那么我刚刚介绍了一个错误,但真正的错误是没有将id作为主键来确保永远不会发生这种情况。 / p>

从对象名称中取出Obj。这似乎是“对象”的缩写,因此是同义的 - 所有编写的.NET代码中的每个其他变量都是针对一个对象的,所以没有必要指出这一点。

*对此更多一点,因为我不想鼓励坏习惯。当只有一个匹配对象时,First获取该对象,而Single获取该对象也确保它是唯一的一个(同样适用于{ {1}}变体除了它们在根本没有找到对象时有所不同。

知道只有一个匹配对象的唯一方法是尝试找到至少两个匹配对象,然后检查你只有一个。如果数据库表在与您的搜索相关的列上建立索引(它是OrDefault而不是TOP 2),则对数据库表的影响很小,但是否则会很严重。

问题是这项检查的重要性。有时你不在乎;使用TOP 1。有时你应该有一种强烈的信心,即只有一个这样的对象;使用First但请检查信心的原因以确保您没有错误(在这种情况下,请检查索引列上是否有主键或唯一键)。如果您确实需要检查,那么请使用First,因为在这种情况下使用Single是错误优化的一个缩影 - 更快但错误绝不是目标。