Wicked Smart Data
LearnInsightsAboutContact
Sign InLet's Build
LearnInsightsAboutContact
Sign InLet's Build
Wicked Smart Data

Intelligence, automation, and expert execution — plus an elite library of free knowledge. We turn complexity into competitive advantage.

Start a conversation

Platform

  • Learning Paths
  • Insights
  • RSS Feed

Company

  • About
  • Contact
  • Work With Us

Legal

  • Privacy Policy
  • Terms of Service

© 2026 Wicked Smart Data. All rights reserved.

Intelligence · Automation · Advantage

All Insights
Power Apps

Configuring Dataverse Table Relationships in Model-Driven Apps: One-to-Many, Many-to-Many, and Cascade Behaviors Explained

Learn how to configure one-to-many and many-to-many relationships in Dataverse, understand cascade behaviors that protect your data integrity, and see exactly how relationships surface inside model-driven app forms. This is the structural knowledge every Power Apps maker needs.

🌱 Foundation18 min readSep 22, 2026Updated Sep 22, 2026
Configuring Dataverse Table Relationships in Model-Driven Apps: One-to-Many, Many-to-Many, and Cascade Behaviors Explained
On this page
  • Introduction
  • Prerequisites
  • What Is a Table Relationship, Really?
  • One-to-Many Relationships: The Foundation of Most Data Models
  • Creating a One-to-Many Relationship
  • How It Surfaces in Model-Driven App Forms
  • Many-to-One: The Same Relationship, Other Direction
  • Many-to-Many Relationships: When the Lines Cross
  • How Many-to-Many Works Under the Hood
  • Creating a Many-to-Many Relationship
  • When to Use N:N vs. Two 1:N Relationships
Cascade Behaviors: What Happens When Records Change
  • The Four Cascade Triggers
  • The Cascade Options
  • Choosing the Right Cascade Behavior
  • Changing Cascade Behaviors
  • Relationships and Security: A Brief but Important Note
  • How Relationships Surface in the Model-Driven App UI
  • Lookup Columns on Forms
  • Subgrids on Parent Forms
  • Associated Views for N:N Relationships
  • Hands-On Exercise
  • Common Mistakes & Troubleshooting
  • Summary & Next Steps
  • Configuring Dataverse Table Relationships in Model-Driven Apps: One-to-Many, Many-to-Many, and Cascade Behaviors Explained

    Introduction

    Picture this: you're building a model-driven app to manage a consulting firm's projects. You've got a Projects table, a Tasks table, a Contacts table, and a Documents table. Everything looks fine in isolation — but when you start thinking about how these tables connect, things get complicated fast. Who owns which tasks? Can a task belong to more than one project? What happens to all the tasks when a project is deleted? These aren't just philosophical questions. They're structural decisions that will either make your app bulletproof or turn it into a tangled mess of orphaned records and broken lookups.

    That's exactly what this lesson is about: table relationships in Dataverse. A relationship is a formal link between two tables that tells Dataverse (and your app) how records in those tables are associated with each other. Get relationships right and your app becomes intuitive, data-consistent, and easy to extend. Get them wrong and you'll spend your time firefighting data integrity issues instead of building features.

    By the end of this lesson, you'll be able to look at a real business scenario, identify the correct relationship type to use, configure it in the Power Apps maker portal, understand exactly what cascade behaviors do and when to change them, and know how relationships surface inside model-driven app forms through subgrids and lookup columns.

    What you'll learn:

    • The difference between one-to-many, many-to-one, and many-to-many relationships — and when each applies
    • How to create and configure relationships in the Dataverse table designer
    • What cascade behaviors are, why they matter, and how to choose the right settings
    • How relationships appear on model-driven app forms as lookups and subgrids
    • Common mistakes that cause orphaned records, permission problems, or accidental data deletion

    Prerequisites

    You should be comfortable with the basics of Dataverse tables, columns, and rows before working through this lesson. If terms like "table," "column," "lookup," or "schema name" are new to you, start with Dataverse Fundamentals: Tables, Columns, and Rows Explained for Power Apps Makers first. It also helps to have read about Designing a Dataverse Data Model: Relationships, Lookups, and Choice Columns, which covers the strategic thinking behind data modeling. Some familiarity with model-driven app forms will help when we discuss how relationships surface in the UI — if you need a primer, check out Building Your First Model-Driven App: Site Map, Tables, Forms, and Views.


    What Is a Table Relationship, Really?

    Before we jump into the types, let's establish a mental model. In Dataverse, a relationship is a mechanism that links rows in one table to rows in another. Under the hood, relationships are implemented using a special kind of column called a lookup column (sometimes called a foreign key in traditional database language). That column stores the unique identifier of a related record.

    For example, if you have a Task row linked to a Project, the Task row contains a lookup column called something like cr123_project that holds the GUID (globally unique identifier) of the parent Project row. Dataverse uses that reference to enforce the relationship, display related records on forms, and determine what happens when a record is deleted.

    This matters because it means relationships are directional. One table "owns" the lookup column, and that asymmetry determines a lot about how the relationship behaves.


    One-to-Many Relationships: The Foundation of Most Data Models

    A one-to-many (1:N) relationship connects one row in a parent table to potentially many rows in a child table. Think of it this way: one Project can have many Tasks, but each Task belongs to exactly one Project.

    In Dataverse terminology:

    • The primary table (also called the "one" side, or parent) is the table a single row lives in — Project
    • The related table (also called the "many" side, or child) is the table that can have multiple rows per parent — Task

    The lookup column always lives on the child table. So in our example, the Task table gets a lookup column pointing to Project. Every task knows which project it belongs to. The project itself doesn't store task references — instead, Dataverse queries all tasks where the project lookup matches the current project's ID.

    Creating a One-to-Many Relationship

    To create a 1:N relationship in the Power Apps maker portal:

    1. Navigate to make.powerapps.com and select your environment.
    2. In the left navigation, click Tables.
    3. Find and open your primary (parent) table — for example, "Project."
    4. In the table designer, click the Relationships tab.
    5. Click Add relationship and choose One-to-many.
    6. In the panel that appears, set the Related (Many) table to your child table — for example, "Task."
    7. Dataverse will auto-generate the lookup column name and relationship name. You can customize these, but be careful — the schema name is permanent once the relationship is saved.
    8. Click Done, then Save table.

    Tip

    Always review the auto-generated schema name before saving. Dataverse will suggest something like cr123_project_task_cr123_projectid, which can be unwieldy. You can shorten it to something like cr123_project_task for cleaner code and flow references later.

    When you save, Dataverse creates the lookup column on the Task table automatically. If you navigate to the Task table and look at its Columns tab, you'll see the new lookup column listed there.

    How It Surfaces in Model-Driven App Forms

    Once you create the relationship, it surfaces in two complementary ways inside your model-driven app:

    On the Task form: The lookup column appears as a searchable lookup field where users can select the parent Project. Users type a few letters and a dropdown of matching Project records appears.

    On the Project form: You can add a subgrid — a mini table view embedded in the form — that shows all related Tasks. This is one of the most powerful UI patterns in model-driven apps. The subgrid displays, filters, and lets users interact with child records directly from the parent record's form. To learn how to add and configure subgrids on your forms, see Designing Model-Driven Forms: Sections, Tabs, Subgrids, and Quick View Forms.


    Many-to-One: The Same Relationship, Other Direction

    You'll sometimes see the term many-to-one (N:1) relationship. This isn't a separate type — it's the same 1:N relationship viewed from the child table's perspective. When you're on the Task table and you add a relationship, you choose "Many-to-one" and select Project as the related table. The result is identical to creating a "One-to-many" from the Project table.

    The distinction matters practically when you're configuring relationships inside the table designer, because the maker portal shows you both N:1 and 1:N relationships in the Relationships tab, labeled by direction. Getting comfortable reading both directions will save you confusion.


    Many-to-Many Relationships: When the Lines Cross

    Sometimes neither table is strictly the parent. Consider the relationship between Contacts and Projects in our consulting firm scenario. A contact (say, a client stakeholder) can be associated with multiple projects. And a project can have multiple contacts. Neither table "owns" the relationship. This is a many-to-many (N:N) relationship.

    How Many-to-Many Works Under the Hood

    Dataverse implements N:N relationships using an intersect table (also called a junction table or bridge table). This is a hidden table that Dataverse creates and manages automatically. It contains two lookup columns: one pointing to each of the two main tables. Each row in the intersect table represents one connection — one Contact linked to one Project.

    You never interact with the intersect table directly in most scenarios. Dataverse handles inserts and deletions there whenever users associate or disassociate records in the app UI.

    Creating a Many-to-Many Relationship

    1. Open either of the two tables you want to connect — for example, "Project."
    2. Click the Relationships tab.
    3. Click Add relationship and choose Many-to-many.
    4. In the panel that appears, set the Related table to "Contact."
    5. Dataverse will auto-generate the intersect table name and relationship name.
    6. Click Done, then Save table.

    Note

    Unlike 1:N relationships, N:N relationships don't create a lookup column on either main table. Instead, they create an entirely separate intersect table. This means you can't filter or sort N:N related records using a simple lookup column — you'll need to work through the intersect table if you're writing advanced queries or flows.

    When to Use N:N vs. Two 1:N Relationships

    Here's a judgment call that trips up many new makers. Should you use a built-in N:N relationship, or should you create your own intersect table manually?

    Use the built-in N:N when:

    • The association itself has no attributes (you just need to know "these two records are connected")
    • You don't need to store any data about the relationship itself

    Create a manual intersect table when:

    • The association has its own properties — for example, a Contact's role on a Project (Lead, Reviewer, Approver)
    • You need to run business rules, flows, or security logic on the association itself

    In that second case, you'd create a "Project Role" table with a lookup to Project and a lookup to Contact, plus a choice column for Role. You now have two 1:N relationships instead of one N:N, but your data model is richer and more flexible.

    Key insight

    The built-in N:N is convenient but inflexible. If there's any chance the relationship will need its own metadata in the future, build the intersect table yourself from the start. Retrofitting this later is painful.


    Cascade Behaviors: What Happens When Records Change

    This is where the real power — and the real danger — of Dataverse relationships lives. Cascade behaviors define what Dataverse automatically does to child records when something happens to the parent record. They control four operations: Assign, Share, Unshare, and Delete.

    Let's use our Project → Task relationship to walk through each.

    The Four Cascade Triggers

    Delete — What happens to Tasks when a Project is deleted? Assign — What happens to Tasks when the Project's owner changes? Share — What happens to Tasks when someone shares the Project with another user? Unshare — What happens to Tasks when sharing on the Project is removed?

    The Cascade Options

    For each trigger, you can choose one of these behaviors:

    Cascade All — The action cascades to every related child record. Delete the project → all tasks are deleted. Reassign the project → all tasks are reassigned.

    Cascade Active — The action cascades only to child records in an active state. Inactive/completed tasks are left alone.

    Cascade User-Owned — The action cascades only to child records owned by the same user as the parent.

    Cascade None — No automatic cascade. Child records are unaffected. This can leave orphaned records — tasks with a project lookup pointing to a deleted project.

    Remove Link — Only available for Delete. Instead of deleting the child records, Dataverse clears the lookup column value, effectively orphaning the child but keeping it alive.

    Restrict — Only available for Delete. Prevents the parent from being deleted if any child records exist. This is your safety net when you absolutely cannot have orphaned records.

    Choosing the Right Cascade Behavior

    Let's think through our scenario carefully:

    For Delete, if you're okay with tasks being removed when their project is removed, use Cascade All. If tasks could have independent value beyond the project (say, they're linked to billing records), use Restrict to force users to manually clean up tasks before deleting a project.

    For Assign, Cascade All is usually the right choice for tasks — if you reassign a project to a new project manager, they probably need to own the tasks too. But for something like Documents attached to a Project, you might want Cascade None if document ownership is managed separately.

    For Share/Unshare, this is deeply tied to your security model. If you're using record-level sharing to give individual users access to a project, cascading share to tasks ensures those users can also see and edit the tasks. See Dataverse Security: Business Units, Security Roles, and Teams for deeper context on why this matters.

    Changing Cascade Behaviors

    To view or change cascade behaviors on an existing relationship:

    1. Open the primary (parent) table in the table designer.
    2. Click the Relationships tab.
    3. Click the relationship name to open its configuration panel.
    4. Scroll down to the Advanced options or Relationship behavior section.
    5. You'll see the current behavior type. Common presets are:
      • Parental — Cascade All for everything (strong ownership)
      • Referential — Cascade None for Delete, Cascade All for Assign/Share (weak link, no delete protection)
      • Referential, Restrict Delete — Cascade None for Delete but Restricted, Cascade All for Assign/Share
      • Custom — Set each trigger independently
    6. Choose your preset or switch to Custom and configure each behavior individually.
    7. Click Done and save the table.

    Warning

    Changing cascade behaviors on a relationship that already has data is risky. If you switch from Restrict to Cascade All on Delete, the next time someone deletes a parent record, all child records will be permanently deleted — with no warning to the user. Test behavior changes in a sandbox environment first, and document your reasoning clearly.


    Relationships and Security: A Brief but Important Note

    Relationships interact with Dataverse security in ways that often surprise new makers. By default, a user's access to a child record is determined by their security role's permissions on that table — not automatically inherited from the parent.

    This means a user could have access to a Project but not be able to see its Tasks if their security role doesn't grant Task access. The cascade Share/Unshare behaviors help with this in record-sharing scenarios, but for role-based access, you need to configure permissions explicitly.

    If you want Tasks to be automatically accessible whenever a user has access to the Project, you can use the Parental cascade behavior combined with role-based privileges, or rely on Model-Driven App Security: Configuring Security Roles, Field Permissions, and Team-Based Access for Table Data to set permissions at the appropriate depth (Organization, Business Unit, Team, or User).


    How Relationships Surface in the Model-Driven App UI

    Configuring a relationship in the table designer is step one. Step two is making sure it actually appears in your app in a useful way. Here's what you need to know.

    Lookup Columns on Forms

    After creating a 1:N relationship, the lookup column appears on the child table. But it won't automatically appear on the form — you need to add it manually. Open the child table's main form in the form designer and drag the lookup column onto the canvas from the column list in the right panel. When a user opens a Task record, they'll see a lookup field showing the current Project, with the ability to search and change it.

    Subgrids on Parent Forms

    On the parent (Project) form, you can add a subgrid to display all related Task records. In the form designer, click the area where you want the subgrid, then in the component panel, add a Subgrid. Configure it to use the Task table and filter by the relationship. You can also set the default view that appears in the subgrid, which is a good reason to invest time in Creating and Customizing Views in Model-Driven Apps: Filters, Sorting, and Editable Grids — a well-crafted view in a subgrid makes a huge usability difference.

    Associated Views for N:N Relationships

    For many-to-many relationships, related records appear in an Associated View — a special view type that's automatically created when you configure an N:N relationship. This view shows all records from the related table that are currently linked to the parent. Users can associate and disassociate records using the toolbar buttons that appear in the associated view panel on the form.


    Hands-On Exercise

    Let's put this together with a practical exercise using the consulting firm scenario.

    Scenario: You have three tables: Project, Task, and Contact. You need to:

    1. Create a 1:N relationship between Project and Task (one project, many tasks)
    2. Set the cascade behavior to Restrict on Delete (can't delete a project with active tasks)
    3. Create an N:N relationship between Project and Contact (projects have multiple contacts, contacts work on multiple projects)

    Step 1: Create the Project → Task relationship

    • Open the Project table → Relationships tab → Add relationship → One-to-many
    • Set Related table to Task
    • Click Done, then save the table
    • Verify: open the Task table and confirm the new lookup column exists in the Columns tab

    Step 2: Change cascade behavior to Restrict Delete

    • On the Project table → Relationships tab → click the Project-Task relationship
    • In the relationship panel, expand Relationship behavior
    • Change the type to Custom
    • Set the Delete behavior to Restrict
    • Leave Assign and Share as Cascade All
    • Save the table

    Step 3: Create the Project ↔ Contact N:N relationship

    • Open the Project table → Relationships tab → Add relationship → Many-to-many
    • Set Related table to Contact
    • Save the table

    Step 4: Verify in the app

    • Open your model-driven app (or create a basic one if you haven't yet)
    • Navigate to a Project record
    • Try to delete a project that has Tasks — you should see an error preventing deletion
    • Navigate to the Project form and look for the associated Contact view panel to verify the N:N relationship is visible

    Tip

    If the associated views or subgrids don't appear automatically after configuring relationships, you may need to add them manually in the form designer. Relationships create the data connections; you still control what appears in the UI.


    Common Mistakes & Troubleshooting

    Mistake 1: Choosing Cascade All for Delete without thinking it through The parental cascade behavior is the default for good reason, but it's a double-edged sword. Deleting a Project will silently and permanently delete all related Tasks, Documents, and any other child records. Always verify what cascade behavior is in place before deploying to production.

    Mistake 2: Trying to create a relationship after importing mismatched data If you import data into a child table with lookup values that don't correspond to valid parent records, Dataverse will reject the rows. Plan your data model and create relationships before bulk importing. If you're dealing with existing data, the Importing and Migrating Data into Dataverse: Excel Import, Dataflows, and Upserts article covers strategies for handling this cleanly.

    Mistake 3: Using N:N when you need a custom intersect table As discussed earlier — if the relationship itself has properties (role, start date, status), the built-in N:N won't support storing them. Build your own intersect table from the start.

    Mistake 4: Forgetting to add lookup columns and subgrids to forms Creating a relationship doesn't automatically update your forms. You need to manually add lookup columns to child forms and subgrids to parent forms in the form designer. This is a surprisingly common source of "where did the relationship go?" confusion.

    Mistake 5: Changing relationship schema names after deployment The schema name of a relationship (and the lookup column it creates) is permanent. If you named it something confusing, you're stuck with it — or you'll need to delete the relationship, rebuild it, and migrate existing data. Invest time in naming conventions before you save.

    Warning

    You cannot delete a relationship while it has data. You must first remove all values from the lookup column (or delete all child records), then delete the relationship. Plan your schema changes accordingly in development before you have real data.


    Summary & Next Steps

    Table relationships are the skeleton of any serious Dataverse data model. Without them, you're just storing isolated lists. With them, you create a connected system where data flows logically between records, forms become interactive and contextual, and your app can enforce real business rules through cascade behaviors.

    Here's what we covered:

    • One-to-many relationships link a single parent record to many child records, using a lookup column on the child table, and surface as lookup fields and subgrids in your app
    • Many-to-many relationships connect two tables without a clear parent, using an auto-managed intersect table, and surface as associated views
    • Cascade behaviors control what happens to child records when a parent is deleted, reassigned, or shared — and choosing the wrong one can cause silent data loss or unintended access changes
    • Form configuration is always a separate step — relationships create the data plumbing, but you manually add lookups and subgrids to make it visible in the UI

    From here, a natural next step is understanding how Formula Columns and Rollup Columns in Dataverse: Calculated Data Without Code can leverage your relationships — for example, rolling up the count of open tasks per project, or calculating a project completion percentage based on related task statuses. You might also explore more advanced relationship patterns like polymorphic lookups, which let a single lookup column point to records in multiple different tables — covered in Polymorphic Lookups in Dataverse: Configuring Regarding Columns, Customer Columns, and Multi-Table Relationships in Model-Driven Apps.

    Work With Us

    From insight to implementation

    Reading is the start. When you're ready to build the data, automation, or AI systems behind it, our team turns strategy into shipped results.

    Let's Build

    Model-Driven Apps & Dataverse

    Previous

    Polymorphic Lookups in Dataverse: Configuring Regarding Columns, Customer Columns, and Multi-Table Relationships in Model-Driven Apps

    Next

    Configuring Dataverse Column-Level Business Rules and Multi-Condition Logic: Combining Visibility, Lock, and Requirement Rules Across Form Scopes

    Related Insights

    Power AppsExpert

    Configuring Dataverse Managed Properties and Solution Component Locking: Controlling Customizability, Preventing Downstream Modifications, and Enforcing ISV-Grade Solution Boundaries in Model-Driven Apps

    28 min
    Power AppsExpert

    Configuring Dataverse Table Capacity and Storage Partitioning: Managing Large-Table Performance, Elastic Tables, and Time-Series Data Strategies in Model-Driven Apps

    31 min
    Power AppsPractitioner

    Configuring Dataverse Environment Variables in Model-Driven App Solutions: Managing Connection References, Default Values, and Deployment-Time Overrides Across Environments

    23 min

    On this page

    • Introduction
    • Prerequisites
    • What Is a Table Relationship, Really?
    • One-to-Many Relationships: The Foundation of Most Data Models
    • Creating a One-to-Many Relationship
    • How It Surfaces in Model-Driven App Forms
    • Many-to-One: The Same Relationship, Other Direction
    • Many-to-Many Relationships: When the Lines Cross
    • How Many-to-Many Works Under the Hood
    • Creating a Many-to-Many Relationship
    • When to Use N:N vs. Two 1:N Relationships
    • Cascade Behaviors: What Happens When Records Change
    • The Four Cascade Triggers
    • The Cascade Options
    • Choosing the Right Cascade Behavior
    • Changing Cascade Behaviors
    • Relationships and Security: A Brief but Important Note
    • How Relationships Surface in the Model-Driven App UI
    • Lookup Columns on Forms
    • Subgrids on Parent Forms
    • Associated Views for N:N Relationships
    • Hands-On Exercise
    • Common Mistakes & Troubleshooting
    • Summary & Next Steps