Skip to content

Codepolice

  • ⤫

Cascade delete in Entity Framework

Posted by Judy Alvarez Posted on February 25, 2022March 3, 2022
0

I had a really hard time getting a simple cascade delete to work with the Entity Framework and I thought I had to write it down here so that I can remember it in the future.

I was trying to delete an item from my database with some children. But I got the error

A relationship is being added or deleted from an AssociationSet ‘FK_ItemChildren_Item’. With cardinality constraints, a corresponding ‘ItemChildren’ must also be added or deleted.

I started to google on it and I found this thread in the MSDN forums. The first suggestion where to add cascade delete to the database and then update the model to get the changes. I did that but I still got the same error. The problem where this.

The SSDL part of the edmx file were updated correctly.

<Association Name="FK_ItemChildren_Item">
 <End Role="Item" Type="Model.Store.Item" Multiplicity="1">
  <OnDelete Action="Cascade" />
 </End>
 <End Role="ItemChildren" Type="Model.Store.ItemChildren"
  Multiplicity="*" />
 <ReferentialConstraint>
 ..
 </ReferentialConstraint>
</Association>

But the CSDL part where not updated:

<Association Name="FK_ItemChildren_Item">
 <End Type="Model.Item" Role="Item" Multiplicity="1">
  <OnDelete Action="Cascade"></OnDelete>
 </End>
 <End Type="Model.ItemChildren" Role="ItemChildren"
  Multiplicity="*">
 </End>
</Association>

The line in “<OnDelete Action=”Cascade”></OnDelete>” was not updated for some reason. When I added that in the model it worked. I guess the designer is not 100% even though the released EF.

UPDATE!

Alexander Muylaert sent me this script via the comments.

Thanks for your blog.  I had this issue on a huge model.  Over 180 tables and hundreds of references.  I didn’t feel like checking all this manually.

I open the edmx file as an xmldocument and executed the following code.  It fixes this issue in batch…  The code is not cleaned, but I have already lost a complete day and I can’t afford to waste more time.  I would like to post this, so someone could use this code and post a cleaned version.

private static string MakeKey(string aAssociation, string aRole) {
        return aAssociation + "_/_" + aRole;
    }

    public static void FixCascadeDeleteIssues(XmlDocument XDOC, XmlNode SSDLNode, XmlNode CSDLNode, ref bool aChanged) {
        HashSet lst = new HashSet();

        foreach (XmlNode SSDLChild in SSDLNode) {
            if (SSDLChild.Name == "Association") {
                foreach (XmlNode EndChild in SSDLChild) {
                    if (EndChild.Name == "End") {
                        foreach (XmlNode DeleteChild in EndChild) {
                            if (DeleteChild.Name == "OnDelete") {
                                var x = DeleteChild.Attributes.GetNamedItem("Action");
                                if (x.Value == "Cascade") {
                                    lst.Add(MakeKey(SSDLChild.Attributes.GetNamedItem("Name").Value, EndChild.Attributes.GetNamedItem("Role").Value));
                                }
                            }
                        }
                    }
                }
            }
        }

        Dictionary FMaps = new Dictionary();

        foreach (XmlNode CSDLChild in CSDLNode) {
            if (CSDLChild.Name == "EntityContainer") {
                foreach (XmlNode ContainerChild in CSDLChild) {
                    if (ContainerChild.Name == "AssociationSet") {
                        foreach (XmlNode EndChild in ContainerChild) {
                            if (EndChild.Name == "End") {
                                string Association = ContainerChild.Attributes.GetNamedItem("Name").Value;
                                string Role = EndChild.Attributes.GetNamedItem("Role").Value;
                                string EntitySet = EndChild.Attributes.GetNamedItem("EntitySet").Value;

                                FMaps.Add(MakeKey(Association, Role), EntitySet);
                            }
                        }
                    }
                }
            }
        }

        foreach (XmlNode CSDLChild in CSDLNode) {
            if (CSDLChild.Name == "Association") {
                string Association = CSDLChild.Attributes.GetNamedItem("Name").Value;

                if (Association == "FK_DEV_PARENT_DEV_ID") {
                    Console.WriteLine("");
                }

                foreach (XmlNode EndChild in CSDLChild) {
                    if (EndChild.Name == "End") {

                        string Multiplicity = EndChild.Attributes.GetNamedItem("Multiplicity").Value;
                        if (Multiplicity == "*") {
                            continue;
                        }

                        string role = EndChild.Attributes.GetNamedItem("Role").Value;
                        string v;
                        if (FMaps.TryGetValue(MakeKey(Association, role), out v)) role = v;
                        string key = MakeKey(CSDLChild.Attributes.GetNamedItem("Name").Value, role);

                        if (lst.Contains(key)) {
                            bool hasdel = false;
                            foreach (XmlNode DeleteChild in EndChild) {
                                if (DeleteChild.Name == "OnDelete") {
                                    var x = DeleteChild.Attributes.GetNamedItem("Action");
                                    if (x.Value == "Cascade") {
                                        hasdel = true;
                                    }
                                }
                            }
                            if (!hasdel) {
                                XmlNode newSub = XDOC.CreateNode(XmlNodeType.Element, "OnDelete", NamespaceDelete);
                                XmlAttribute xa = XDOC.CreateAttribute("Action", null);
                                xa.Value = "Cascade";
                                newSub.Attributes.Append(xa);
                                EndChild.AppendChild(newSub);
                                aChanged = true;
                            }
                        }
                    }
                }
            }
        }
    }
Categories: JavascriptTagged: .net core 5 mvc, .net mvc core, asp net and mvc difference, asp net core mvc login and registration using identity, asp net core mvc vs asp net mvc, asp net mvc 4 tutorial, asp net mvc application, asp net mvc certification, asp net mvc chart, asp net mvc codeproject, asp net mvc convert html to pdf, asp net mvc course, asp net mvc dersleri, asp net mvc ecommerce open source, asp net mvc electronic signature, asp net mvc generate pdf, asp net mvc jobs, asp net mvc print pdf, asp net mvc templates, c# asp net mvc, html to pdf asp net mvc, interview questions on asp net mvc, latest version of asp net mvc, mvc application example asp net c#, mvc vs net core, net mvc datepicker, online asp .net mvc 5 test, pdf viewer asp net mvc, signalr chat application with database in asp net mvc, vb net mvc

Post navigation

Previous Previous post: ASP.NET membership: System.Web.Security. SqlRoleProvider problems
Next Next post: Generate expiring urls for Amazon S3 via a WordPress Plugin

Related Posts

  • Bringing Python apps into Node

    #​596 — October 14, 2025 Read on the Web 📂 A Modern Guide to Reading and Writing Files in Node — A comprehensive guide to various methods for working with files, from promise-based methods through to working with streams, processing files concurrently, using file handles, and memory-efficient techniques. Luciano Mammino A Way to Integrate Python ASGI with Node.js

    Posted by Posted on October 14, 2025
    0
  • Vite gets its own documentary

    #​756 — October 10, 2025 Read on the Web JavaScript Weekly ▶  Vite: The Documentary — From the same creators of the fantastic ▶️ Node.js, ▶️ Angular and ▶️ React documentaries comes an up to date look at Vite, the build tool that has taken the JavaScript ecosystem by storm in recent years. Many luminaries make an appearance to

    Posted by Posted on October 10, 2025
    0
  • npm security best practices to consider

    #​595 — October 7, 2025 Read on the Web 15 Recent Node Features That Can Replace Popular npm Packages — Many features that once required third-party packages are now built into the runtime itself. Here’s a look at some of the most notable that you may want to experiment with, prior to reducing unnecessary dependencies. Lizz

    Posted by Posted on October 7, 2025
    0
  • React 19.2 is in the building

    #​755 — October 3, 2025 Read on the Web JavaScript Weekly The State of JavaScript 2025 Survey — Each year, Devographics runs an epic survey of as many JavaScript community members as it can and turns the results into an interesting report on the state of the ecosystem – here’s the results from 2024. If

    Posted by Posted on October 3, 2025
    0
  • Using Node with Cloudflare Workers

    #​594 — September 30, 2025 Read on the Web 🗓️ We’re back after taking a week off for my birthday. I’ve never bothered to do that before, but I figured I’d give it a go, and.. it was good 😅 We’re now back every week until Christmas!__Peter Cooper, your editor A Year of Improving Node.js

    Posted by Posted on September 30, 2025
    0
  • The first browser with JavaScript landed 30 years ago

    #​754 — September 26, 2025 Read on the Web JavaScript Weekly Give Your AI Eyes: Introducing Chrome DevTools MCP — The Chrome team has released an MCP server for Chrome DevTools, enabling agents like Claude Code or OpenAI Codex to use the DevTools to debug and analyze the performance and behavior of your webapps (or

    Posted by Posted on September 26, 2025
    0
Judy Alvarez

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Codepolice

  • Github
  • Atlassian
  • Flatlogic
  • Xero
  • Jetbrains
  • Figma
  • Bringing Python apps into Node
  • Vite gets its own documentary
  • npm security best practices to consider
  • React 19.2 is in the building
  • Using Node with Cloudflare Workers
https://flatlogic.com/generator
COPYRIGHT © 2025 - Codepolice