Dynamics 365 Virtual Entities: Cross-System Federation, CRUD Capabilities & Limitations

Type: ERP Integration System: Microsoft Dataverse (2024 Wave 2+) + Dynamics 365 F&O (10.0.12+) Confidence: 0.91 Sources: 8 Verified: 2026-03-01 Freshness: 2026-03-01

TL;DR

System Profile

Dataverse virtual entities are a platform-level feature of Microsoft Dataverse that project external data as if it were native Dataverse tables. The external data is never copied — every Create, Retrieve, RetrieveMultiple, Update, and Delete operation is translated into a call to the external data source in real time. [src1]

For Finance & Operations (F&O) apps specifically, Microsoft provides a dedicated virtual entity provider that maps all OData-enabled F&O entities into Dataverse. This is the primary mechanism for cross-system federation between customer engagement apps (Sales, Service, Marketing) and F&O apps (Finance, Supply Chain Management, Human Resources). [src2]

PropertyValue
VendorMicrosoft
SystemMicrosoft Dataverse + Dynamics 365 Finance & Operations
API SurfaceOData v4 Data Provider (built-in), Azure Cosmos DB (Marketplace), Custom Data Providers (.NET plug-ins), F&O Virtual Entity Provider
Current VersionDataverse 2024 Wave 2+; F&O 10.0.12+
Editions CoveredAll licensed Power Platform environments; F&O: Finance, Supply Chain, HR, Commerce
DeploymentCloud (on-premises excluded from service protection)
API DocsVirtual Tables (Dataverse)
StatusGA

API Surfaces & Capabilities

Virtual entities operate through data providers that translate Dataverse operations into external system calls. Three provider types are available plus a dedicated F&O provider. [src1, src4, src8]

Data ProviderProtocolBest ForCRUD SupportReal-time?External AuthNotes
OData v4 (built-in)HTTPS/ODataAny OData v4 endpointFull CRUDYesHeader/query string paramsDefault provider; maps Edm types to Dataverse types
Azure Cosmos DBHTTPS/RESTDocument databasesFull CRUDYesConnection stringAzure Marketplace
Custom Data Provider.NET Plug-insAny data sourceFull CRUD via plug-inYesDeveloper-definedRegister plug-ins for Create, Retrieve, RetrieveMultiple, Update, Delete
F&O ProviderSSL/TLS 1.2 S2SFinance & Operations OData entitiesFull CRUDYesMicrosoft Entra S2SCDSVirtualEntityAdapterService translates queries; F&O business logic invoked

Rate Limits & Quotas

Per-Request Limits

Limit TypeValueApplies ToNotes
Column selectionAll columns returnedDataverse virtual tables$select not applied server-side — all attributes returned [src1]
FK expansion latencySignificant per navigation propertyDataverse virtual tablesEach FK column triggers additional round-trip [src6]
OData timeoutConfigurable (default 30s)OData v4 Data ProviderSet in data source configuration [src4]
F&O latency overhead<30ms per call (co-located)F&O virtual entitiesSame Azure region required [src2]

Rolling / Daily Limits (F&O Backend)

Limit TypeValueWindowNotes
Requests per user per web server6,0005-min sliding windowPer throttling key (user + app ID) [src5]
Combined execution time per user1,200 seconds (20 min)5-min sliding windowAcross all requests for the user [src5]
Concurrent requests per user52Per web serverMultiple web servers in production [src5]
Resource-based throttlingDynamicContinuousTriggered by high CPU/memory across all integrations [src5]

Important: F&O virtual entity calls are exempt from F&O service protection API limits when Power Platform integration is enabled. However, Dataverse service protection API limits still apply. [src5]

Authentication

FlowUse WhenMechanismRefresh?Notes
F&O S2S (Microsoft Entra)F&O virtual entities in DataverseEntra app registration → S2S tokenPer-requestCDSVirtualEntityApplication role required [src2]
OData v4 header authExternal OData endpointsCustom header parametersN/AUp to 10 parameters [src4]
OData v4 query stringExternal OData endpointsCustom query string paramsN/AToggle between header/query string [src4]
Custom provider authAny external systemDeveloper-implementedDeveloper-definedHandle auth in .NET plug-in code [src8]

Authentication Gotchas

Constraints

Integration Pattern Decision Tree

START — User needs to access external data from Dataverse/Power Platform
├── Does the user need data replicated INTO Dataverse?
│   ├── YES — need auditing, search, calculated fields, or offline
│   │   ├── Real-time bidirectional? → Dual Write
│   │   └── Batch ETL? → DMF or Azure Synapse Link
│   └── NO — federated read/write acceptable
│       ├── External source is Finance & Operations?
│       │   ├── YES → F&O Virtual Entities (built-in provider)
│       │   └── NO ↓
│       ├── External source exposes OData v4?
│       │   ├── YES → OData v4 Data Provider (built-in)
│       │   └── NO ↓
│       ├── Azure Cosmos DB?
│       │   ├── YES → Cosmos DB provider (Marketplace)
│       │   └── NO → Custom Data Provider (.NET plug-ins)
├── Data volume
│   ├── < 1K records/day → Virtual entities fine
│   ├── 1K-10K records/day → Optimize with $select, pagination
│   └── > 10K records/day → Consider Dual Write or DMF instead
└── Need charts, dashboards, search, or auditing?
    ├── YES → Cannot use virtual entities; replicate to native tables
    └── NO → Virtual entities are the right choice

Quick Reference

F&O Virtual Entity Setup Checklist

StepActionWhereVerification
1Enable Power Platform integrationPower Platform admin centerEnvironment shows "Linked"
2Install required solutionsAuto-installed with integrationVerify Dynamics365Company, MicrosoftOperationsVESupport, ERPCatalog, ERPVE
3Find entity in catalogAdvanced Find → "Available finance and operations entities"Entity appears in list
4Make entity visibleOpen entity → check "Visible" → SaveVirtual entity appears in Advanced Find
5Refresh metadata (after F&O changes)Open entity → check "Refresh" → SaveUpdated columns appear
6Reference in ISV solutionAdd existing → Table → select virtual entityHard dependency on MicrosoftOperationsERPVE

OData v4 Provider Data Type Mappings

OData EDM TypeDataverse TypeSupported?Notes
Edm.GuidUnique IdentifierYesRequired for primary key [src4]
Edm.StringSingle/Multi Line TextYes
Edm.Int32Whole NumberYesCannot map to primary key [src4]
Edm.Int64Whole NumberYes
Edm.DecimalDecimal/CurrencyYes
Edm.DoubleFloating PointYes
Edm.BooleanTwo OptionsYes
Edm.DateTimeDate and TimeYes
Edm.DateTimeOffsetDate and TimeYes
Edm.BinaryNoNot supported [src4]
Edm.FloatNoNot supported [src4]
Edm.Int16NoNot supported [src4]
Edm.Byte / Edm.SByteNoNot supported [src4]
Edm.TimeNoNot supported [src4]

Step-by-Step Integration Guide

1. Configure OData v4 Virtual Table Data Source

Create a data source pointing to your external OData endpoint. [src4]

  1. Navigate to Settings > Administration > Virtual Entity Data Sources
  2. Click New and select OData v4 Data Provider
  3. Set the URI to your OData service root
  4. Set Timeout (default 30 seconds)
  5. Choose Pagination mode: client-side (default) or server-side ($skiptoken)
  6. Add authentication headers/query strings (up to 10 parameters)
  7. Save

Verify: Navigate to Virtual Entity Data Sources list → new source appears with status Active.

2. Create the Virtual Table Definition

Map your external entity to a Dataverse virtual table. [src1]

  1. Go to Power AppsTablesNew tableVirtual table
  2. Select the data source created in Step 1
  3. Map the entity name and primary key (must be Edm.Guid)
  4. Map columns: external field names to Dataverse column definitions
  5. Define relationships (lookups) to other tables if needed

Verify: Open the new table in Advanced Find → records from external source appear.

3. Query Virtual Table via Web API

Read records from the virtual table through the Dataverse Web API. [src6]

GET [Organization URI]/api/data/v9.2/new_externalproducts?$select=new_name,new_price,new_category&$filter=new_category eq 'Electronics'&$top=50
Accept: application/json
OData-MaxVersion: 4.0
OData-Version: 4.0

Verify: HTTP 200 response with value array containing external records.

4. Perform CRUD Operations

Write operations work identically to native Dataverse tables. [src1, src7]

POST [Organization URI]/api/data/v9.2/new_externalproducts
Content-Type: application/json

{
  "new_name": "Widget Pro",
  "new_price": 29.99,
  "new_category": "Electronics"
}

Verify: HTTP 204 response with OData-EntityId header. Confirm record exists in external source.

Code Examples

Python: Query F&O Virtual Entity via Dataverse Web API

# Input:  Microsoft Entra app credentials, Dataverse environment URL
# Output: List of F&O customer records surfaced as virtual entities

import requests
from msal import ConfidentialClientApplication

app = ConfidentialClientApplication(
    client_id="YOUR_APP_ID",
    client_credential="YOUR_CLIENT_SECRET",
    authority="https://login.microsoftonline.com/YOUR_TENANT_ID"
)
token = app.acquire_token_for_client(
    scopes=["https://YOUR_ORG.crm.dynamics.com/.default"]
)

headers = {
    "Authorization": f"Bearer {token['access_token']}",
    "OData-MaxVersion": "4.0",
    "OData-Version": "4.0",
    "Accept": "application/json",
    "Prefer": "odata.maxpagesize=100"
}

# Use $select to avoid FK overhead
url = "https://YOUR_ORG.crm.dynamics.com/api/data/v9.2/mserp_custcustomerv3entities"
params = {
    "$select": "mserp_customeraccount,mserp_organizationname,mserp_customergroupid",
    "$filter": "mserp_customergroupid eq '10'",
    "$top": "50"
}

response = requests.get(url, headers=headers, params=params)
response.raise_for_status()
customers = response.json().get("value", [])

C#/.NET: CRUD on Virtual Table via SDK

// Input:  IOrganizationService from Dataverse SDK
// Output: Created/updated/deleted record in external system

var record = new Entity("new_externalproduct");
record["new_name"] = "Widget Pro Max";
record["new_price"] = new Money(49.99m);

// Create passes through to external data source
Guid newId = service.Create(record);

// Update
record.Id = newId;
record["new_price"] = new Money(44.99m);
service.Update(record);

// Delete
service.Delete("new_externalproduct", newId);

PowerShell: Enable F&O Virtual Entity

# Input:  Dataverse environment URL, F&O entity logical name
# Output: Virtual entity becomes visible in Dataverse

Install-Module -Name Microsoft.Xrm.Data.PowerShell -Scope CurrentUser
$conn = Connect-CrmOnline -ServerUrl "https://YOUR_ORG.crm.dynamics.com"

$catalog = Get-CrmRecords -conn $conn `
  -EntityLogicalName "mserp_finabortenvironmententity" `
  -FilterAttribute "mserp_physicalname" `
  -FilterOperator "eq" `
  -FilterValue "CustCustomerV3Entity"

$entityId = $catalog.CrmRecords[0].Id
Set-CrmRecord -conn $conn `
  -EntityLogicalName "mserp_finabortenvironmententity" `
  -Id $entityId `
  -Fields @{ "mserp_hasbeengenerated" = $true }

Data Mapping

OData EDM to Dataverse Type Gotchas

Source TypeTarget TypeTransformGotcha
Edm.GuidUnique IdentifierDirectMust be primary key — no alternatives [src4]
Edm.Int32Whole NumberDirectCannot serve as primary key [src4]
Edm.String (>4000 chars)Multiple Lines of TextDirectCheck max length constraints on external side
Edm.DateTimeOffsetDate and TimeTimezone conversionDataverse stores UTC; external may use local time
Edm.DecimalCurrencyCurrency entity mappingCurrency lookup must exist in Dataverse
Nullable=False propertiesBusiness RequiredMust alignMismatch causes silent save failures [src4]

Data Type Gotchas

Error Handling & Failure Points

Common Error Codes

CodeMeaningCauseResolution
429Too Many Requests (Dataverse)Exceeded 6,000 requests in 5-min window or 52 concurrentExponential backoff with Retry-After header [src5]
429 (F&O)Too Many Requests (resource-based)High CPU/memory utilization on F&O web serversReduce concurrency; check throttling prioritization [src5]
400Bad RequestNullable property mismatch or unsupported EDM typeVerify external field nullability matches Dataverse field requirement [src4]
InternalServerErrorF&O timeoutQuery too complex or F&O service unavailableIncrease timeout; simplify query [src6]
"Unable to determine the user in CDS"Missing user mappingS2S call used SYSTEM user without proper contextUse org context with appropriate app/user with F&O permissions [src2]
Entity not foundVirtual entity not visibleEntity not enabled in catalogCheck "Visible" checkbox in catalog [src3]

Failure Points in Production

Anti-Patterns

Wrong: Including all columns in virtual table grid views

// BAD — fetches all columns including FK navigation properties
GET /api/data/v9.2/mshr_hcmworkerbaseentities
// Triggers cascading round-trips to F&O for each FK column
// Causes throttling on datasets > 100 records

Correct: Use $select to exclude FK columns

// GOOD — explicitly select only needed columns
GET /api/data/v9.2/mshr_hcmworkerbaseentities?$select=mshr_name,mshr_firstname,mshr_lastname,mshr_personnelnumber
// 50-80% faster; avoids FK round-trips [src6]

Wrong: Using virtual entities for bulk data migration

// BAD — 50,000 sequential S2S calls via virtual entities
for (int i = 0; i < 50000; i++)
{
    var record = new Entity("mserp_vendvendortablev2entity");
    record["mserp_vendoraccountnumber"] = vendors[i].AccountNumber;
    service.Create(record);  // Each = round-trip to F&O
}
// Hours of runtime + throttled at 6,000/5min

Correct: Use DMF for bulk operations

// GOOD — use Data Management Framework for bulk operations
// Virtual entities are for real-time federated access, not ETL
// DMF supports parallel processing with configurable batch sizes
// Use DMF REST API: POST /data/DataManagementDefinitionGroups/
//   Microsoft.Dynamics.DataEntities.ImportFromPackage

Wrong: Assuming auditing captures virtual entity changes

// BAD — relying on Dataverse audit for virtual entity records
// Auditing is NOT supported for virtual tables [src1]

Correct: Implement change tracking on external system

// GOOD — use F&O entity change tracking or external audit logs
// For F&O: enable change tracking on data entity in AOT
// For custom providers: log changes in plug-in handlers

Common Pitfalls

Diagnostic Commands

# Check if F&O virtual entities solution is installed (PowerShell)
Get-CrmRecords -conn $conn -EntityLogicalName "solution" \
  -FilterAttribute "uniquename" -FilterOperator "like" \
  -FilterValue "MicrosoftOperations%"

# List all visible F&O virtual entities
GET [Org URI]/api/data/v9.2/mserp_finabortenvironmententities?\
  $filter=mserp_hasbeengenerated eq true\
  &$select=mserp_physicalname,mserp_hasbeengenerated

# Test virtual entity access (simple retrieve)
GET [Org URI]/api/data/v9.2/mserp_custcustomerv3entities?$top=1\
  &$select=mserp_customeraccount

# Check API limits via response headers
# Look for: x-ms-ratelimit-burst-remaining-xrm-requests
# And: Retry-After header on 429 responses

# Enable plug-in tracing for virtual entity errors
# Settings > Administration > System Settings > Customization tab
# Then check: Settings > Plug-In Trace Log

Version History & Compatibility

FeatureReleaseStatusNotes
Virtual tables (OData v4 provider)Dataverse 2017GAOriginal release — read-only
CRUD support for OData v4 provider2020 Wave 2GAFull Create, Update, Delete added [src1]
Custom data provider CRUD2020 Wave 2GAPlug-in registration for all 5 operations [src8]
F&O virtual entitiesF&O 10.0.12GAFull CRUD for F&O OData entities [src2]
Azure Cosmos DB provider2021GAAzure Marketplace [src1]
Virtual Table Creation Wizard2024 Wave 2PreviewNo-code for SharePoint and SQL sources
User-based API limits removed for F&O10.0.36GAOptional limits disabled; resource-based remain [src5]

When to Use / When Not to Use

Use WhenDon't Use WhenUse Instead
Real-time federated access without data duplicationNeed auditing, search, or calculated columnsDual Write or DMF to replicate into native Dataverse tables
Power Apps/Power Automate needs F&O entity accessBulk migration (>10K records)Data Management Framework or Azure Synapse Link
Cross-app experiences (CE + F&O) without sync lagNeed charts, dashboards, or advanced visualizationsReplicate to Dataverse or Power BI DirectQuery
Low-volume CRUD (<1K operations/day)Need field-level security or user-owned filteringNative Dataverse tables with proper security model
Prototyping before committing to Dual WriteHigh-concurrency (>50 users on same virtual entity)Dual Write for replicated low-latency access
Portal access to F&O with user-context securityOffline-capable mobile appsReplicate to native tables for offline sync

Important Caveats

Related Units