π€ Entities, forms, views, relationships, roles, and permissions
>> "My current project is a Model-Driven App (CRM) with Business Central integration. My role focuses on implementing entities, forms, views, relationships, roles, and permissions. However, I feel that I donβt yet have a complete overview of how the whole system works. I can connect small pieces, but I donβt fully see the big picture."
---
#οΈβ£ The Mental Model: A Database with a Living Face
The most important thing to understand about Model-Driven Apps (MDAs) is that they are not built like traditional applications. Most software is built code-first β a developer writes logic, and the UI is crafted around that logic. MDAs flip this: they are data-model first. Everything you see on screen β forms, views, dashboards β is generated automatically from the underlying data structure you define. This is why they're called "model-driven."
Think of it this way: you define the shape of your data, and the app emerges from that shape.
#οΈβ£ The Four Layers (and How They Stack)
It helps to think of the whole system as four distinct layers sitting on top of each other.
1οΈβ£ Layer 1 β The Data Layer (Dataverse)
At the very bottom is Microsoft Dataverse, which is essentially a cloud-hosted relational database with superpowers. Every "entity" you create (like Account, Contact, Opportunity, or a custom one) is really just a table in Dataverse. The columns (fields) you add to that entity are the columns of that table. The relationships you define between entities are foreign keys β Dataverse just makes them feel more semantic (one-to-many, many-to-many, etc.).
This layer is the source of truth. Everything else in the app is a view into or interface over this layer.
2οΈβ£ Layer 2 β The Metadata Layer (the "Model")
On top of the raw data sits metadata β the definitions of how data relates, behaves, and validates. This includes your relationships (which entities are connected and how), field types and validation rules, and crucially, Business Rules (declarative logic you define without code, like "if Status = Closed, make Revenue required"). The metadata layer is what makes this a model-driven app β the model is this rich description of your data and its rules.
3οΈβ£ Layer 3 β The Presentation Layer (Forms, Views, Dashboards)
This is what your users actually see. Forms are the detail screens for a single record. Views are the list screens showing multiple records filtered and sorted. Dashboards aggregate views and charts. The crucial insight is that none of these are custom-coded UIs β they're configurations that tell the runtime engine how to render the data from Layer 1 according to the rules in Layer 2. When you drag fields onto a form, you're authoring a configuration, not writing UI code.
4οΈβ£ Layer 4 β The Security Layer (Roles & Permissions)
This layer sits across all the others like a gatekeeper. Roles in Dataverse aren't just login permissions β they're record-level and field-level access policies that control not just whether a user can open the app, but whether they can read, create, write, delete, append, or share each specific table, and at what scope (their own records, their business unit's records, or the entire organization). This is why security in MDAs feels more complex than typical app auth β it's genuinely more granular.
#οΈβ£ How the Pieces You Work With Fit In
Now that you have the layers, let me map your daily work onto them:
When you implement an entity, you're working in Layer 1 β you're defining a table in Dataverse. When you add relationships, you're also in Layer 1/2 β you're creating the relational links that Dataverse will enforce and that the UI will later use to render related record grids (subgrids on forms) and lookups. When you build forms and views, you're in Layer 3 β you're configuring the rendering of that data model. When you assign roles and permissions, you're in Layer 4.
The reason it can feel disconnected is that each of these tasks lives in a different part of the maker portal and uses different mental vocabulary β but they're all serving the same underlying data model.
#οΈβ£ Where Business Central Fits
Business Central (BC) is where the financial and operational reality lives β inventory, invoices, purchase orders, GL entries. Your CRM (the MDA) is where the customer relationship reality lives β leads, opportunities, accounts, service cases.
The integration between them is essentially a bridge between two separate data stores. There are a few common patterns for how this bridge works. The most common in Microsoft's ecosystem is Dataverse-linked tables (formerly called "virtual entities"), where a BC record appears inside Dataverse without being copied β it's fetched live from BC when needed. Another pattern is Power Automate flows that sync data between the two systems on triggers (e.g., when an Opportunity is marked Won in the CRM, a flow creates a Sales Order in BC). A third is dual-write, a near-real-time synchronization framework that keeps certain tables in sync bidirectionally.
The key question to ask on your project is: which direction does authority flow? Meaning, if a customer's address changes, does BC or Dataverse "own" that record? Whichever system is the system of record for a given entity will typically be the one that writes, and the other one reads or receives a copy.
#οΈβ£ The Thread That Ties It All Together
Here's the single most useful thing to hold in your head: a Model-Driven App is a configured runtime, not a coded application. The Power Platform runtime engine reads your metadata (your model) and generates the application on the fly. When a user opens a form, the engine asks: "What fields does this entity have? What form layout has been configured? What does this user's security role permit them to see?" β and then it renders accordingly.
This means that when something behaves unexpectedly (a field is missing, a button is gone, a related grid isn't showing), the debugging instinct should always be: which layer is responsible? Is the data not there (Layer 1)? Is a business rule hiding the field (Layer 2)? Is the form not configured to show it (Layer 3)? Or does the user's role not grant read access to it (Layer 4)?
If you internalize that four-layer model and train yourself to ask "which layer is this?" for every problem or task, the big picture will start to feel much more coherent.