Retrieve All One-to-Many Relationships and Cascade Delete Behavior for a Dataverse Table Using C#


While working on a Dynamics 365 Field Service cleanup, we needed to delete a large number of Work Order records.

Before doing so, we wanted to understand exactly what would happen to the related records.

Not every relationship is configured for Cascade Delete. Many use RemoveLink, which doesn’t delete the child records. Instead, Dataverse updates the lookup field to null by removing the relationship.

This behavior is easy to overlook, but it can have unintended consequences. In our case, several integrations were listening for updates on child tables. Deleting a Work Order could therefore generate a large number of update events on related records, potentially triggering unnecessary integration processing.

To identify every table referencing msdyn_workorder along with its delete behavior, I wrote a small console application that retrieves the relationship metadata and exports it to a CSV file.

The application uses the RetrieveEntityRequest message to retrieve all one-to-many relationships for a Dataverse table along with their cascade settings.

static void Main(string[] args)
{
    Console.WriteLine("Connecting...");

    string connectionString =
        ConfigurationManager.AppSettings["ConnectionString"];

    var service = new ServiceClient(connectionString);

    if (!service.IsReady)
    {
        Console.WriteLine("Connection Failed");
        Console.WriteLine(service.LastError);
        Console.ReadLine();
        return;
    }

    Console.WriteLine("Connected Successfully");

    var request = new RetrieveEntityRequest
    {
        LogicalName = "msdyn_workorder",
        EntityFilters = EntityFilters.Relationships
    };

    var response =
        (RetrieveEntityResponse)service.Execute(request);

    var relationships = new List<RelationshipInfo>();

    foreach (var relationship in response.EntityMetadata.OneToManyRelationships)
    {
        relationships.Add(new RelationshipInfo
        {
            SchemaName = relationship.SchemaName,
            ParentTable = relationship.ReferencedEntity,
            ChildTable = relationship.ReferencingEntity,
            LookupAttribute = relationship.ReferencingAttribute,
            DeleteCascade = relationship.CascadeConfiguration.Delete.ToString(),
            AssignCascade = relationship.CascadeConfiguration.Assign.ToString(),
            ShareCascade = relationship.CascadeConfiguration.Share.ToString(),
            ReparentCascade = relationship.CascadeConfiguration.Reparent.ToString()
        });
    }

    Console.WriteLine($"Relationships Found: {relationships.Count}");

    foreach (var relationship in relationships)
    {
        Console.WriteLine(
            $"{relationship.ChildTable} | " +
            $"{relationship.LookupAttribute} | " +
            $"{relationship.DeleteCascade}");
    }

    using (var writer = new StreamWriter("WorkOrderRelationships.csv"))
    using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
    {
        csv.WriteRecords(relationships);
    }

    Console.WriteLine("CSV exported successfully.");
}

RelationshipInfo Class

public class RelationshipInfo
{
    public string SchemaName { get; set; }
    public string ParentTable { get; set; }
    public string ChildTable { get; set; }
    public string LookupAttribute { get; set; }
    public string DeleteCascade { get; set; }
    public string AssignCascade { get; set; }
    public string ShareCascade { get; set; }
    public string ReparentCascade { get; set; }
}

The output :

Why is this useful?

This utility can be useful when we need to:

  • Review cascade behavior before performing bulk deletes.
  • Understand which child tables will be deleted, updated, or left unchanged.
  • Identify RemoveLink relationships that generate automatic update events on child records.
  • Validate plugin and integration behavior before data cleanup activities.
  • Export relationship metadata for documentation or analysis.

The code works for any Dataverse table. Simply replace:

LogicalName = “msdyn_workorder”

with the logical name of the table you want to analyze.

In our case, this quick analysis helped us identify child tables that would receive automatic updates due to RemoveLink relationships, allowing us to ensure those updates did not unnecessarily trigger downstream integrations during the cleanup process.

Hope it helps..

Advertisements

Discover more from Nishant Rana's Weblog

Subscribe to get the latest posts sent to your email.

Unknown's avatar

Author: Nishant Rana

I love working in and sharing everything about Microsoft.NET technology !

Please share your thoughts

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Discover more from Nishant Rana's Weblog

Subscribe now to keep reading and get access to the full archive.

Continue reading

Power Platform Puzzles

D365 CRM, Power Platform Tips &Tricks

Power Spark

Power Spark By Shrangarika

Van Carl Nguyen

Exploration of Power Platform

My Trial

It is my experience timeline.

Arpit Power Guide

a guide to powering up community

Welcome to the Blog of Paul Andrew

Sponsored by Cloud Formations Ltd

Deriving Dynamics 365

Deriving Solutions and features on Power Platform/Dynamics 365

The CRM Ninja

Thoughts & musings from a Microsoft Business Applications Ninja!

D CRM Explorer

Learn about Microsoft Dynamics CRM Power Platform customization and implementation and other cool stuffs

Stroke // Jonas Rapp

I know pre-stroke. I will improve who I was.

Power Melange

Power Melange By Shalinee

Clavin's Blog - PPUG.ORG

AI - Power Automate - Power Apps - SharePoint Online - Azure - Nintex - K2 - Artificial Intelligence

Sat Sangha Salon

An Inquiry in Being

The Indoencers

The Influencers & Influences of Indian Music

Monika Halan's blog

Hand's-free money management

D365 Demystified

A closer look at Microsoft Dynamics 365.

Microsoft Mate (msftmate) - Andrew Rogers

Experienced consultant primarily focused on Microsoft Dynamics 365 and the Power Platform

Manmit Rahevar's Blog

One Stop Destination for Microsoft Technology Solutions

MG

Naturally Curious

Brian Illand

Power Platform and Dynamics 365

Steve Mordue

The Professional Paraphraser

Subwoofer 101

Bass defines your home theater

SQLTwins by Nakul Vachhrajani

SQL Server tips and experiences dedicated to my twin daughters.

Everything D365

Discovering Azure DevOps and D365 Business Applications

Tech Wizard

Lets do IT Spells

XRM Tricks (Power Platform & Dynamics CRM )

Power Platform & Dynamics CRM

CRM TIPS BY PRM

Mail to crmtipsbyprm@gmail.com for queries and suggestions

nijos.dev

Giving back to the community what I have learned

Power Platform Learning

Your Go-To Resource for Power Apps, Power Automate & More

xrm CRM Dynamics

Dynamics CRM Technical & Functional Info

Dynamics 365 Blogs - Explained in unique way

Sometimes you need to look at things from different perspective.

CRM Keeper

Dynamics 365 Customer Engagement, CRM, Microsoft CRM, Dynamics CRM