0

可能重复:
删除实体框架中的对象及其所有子对象?

这段代码:

        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);

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

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

有没有办法改进逻辑?

4

1 回答 1

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 针对 a List<T>)*。当然,如果有可能存在两个具有相同 id 的站点,那么我刚刚引入了一个错误,但真正的错误在于没有将 id 作为主键以确保永远不会发生这种情况。

取出Obj对象的名称。这似乎是“对象”的缩写,因此是重言式 - 曾经编写的每段 .NET 代码中的所有其他变量都是针对对象的,因此指出这一点没有意义。

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

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

问题是这对于进行检查有多重要。有时你不在乎;使用First. 有时你应该对只有一个这样的对象有很强的信心;使用First但请检查该信心的原因以确保您没有错误(在这种情况下,请检查索引列上是否有主键或唯一键)。如果您真的需要检查,那么请务必使用Single,因为First在这种情况下使用是糟糕优化的缩影——更快但错误绝不是目标。

于 2012-08-26T10:46:13.877 回答