Skip to main content
All docs
V25.1
  • Shared Data Support in a Multi-Tenant Application

    • 4 minutes to read

    In multi-tenant applications, the host database can maintain shared business objects accessible to tenants. Shared data is helpful when storing master tables, such as currency, tax, and other global application settings. Tenant users can read these shared data tables, but cannot modify table data. Host UI administrators have complete CRUD control over host and tenant data through code.

    Key Security Points

    • The host admin has full access to tenant business objects.
    • A tenant user has read-only access to host shared business objects.
    • A tenant user does not have access to another tenant’s business objects.

    Access Host Shared Business Objects from a Tenant

    Register host object types as shared to indicate that all tenants have read-only access to corresponding data. Data types associated with shared types must also be registered as shared types. Otherwise, access to associated objects is denied.

    1. Use the WithSharedBusinessObjects (EF Core) / WithSharedBusinessObjects (XPO) method to register shared host object types in the application builder.

      public class Startup { 
          public void ConfigureServices(IServiceCollection services) { 
              // ... 
              builder.AddMultiTenancy() 
                  .WithSharedBusinessObjects(typeof(SharedEntityType1), typeof(SharedEntityType2), ...) 
                  // ... 
          } 
      } 
      

      If an application uses middle-tier security, the shared types should be registered on the server and client side.

    2. The list below contains methods that return the Object Space for shared data. When calling these methods, set the generic type parameter to the shared object type and the tenantName parameter to null. Once you obtain the Object Space, access required data in the same manner as you would do with regular business objects.

      var objectSpace = Application.CreateObjectSpace<SharedEntityType1>(null));
      

    Tip

    In tenant accounts, you can use CreateObjectSpace methods without the tenantName parameter to get the same result.

    Example

    The following code sample registers the TaxRate type as a shared type and accesses TaxRate objects in code:

    builder.AddMultiTenancy() 
        .WithSharedBusinessObjects(typeof(TaxRate)) 
        // ...
    
    decimal CalculateTax() { 
        using (var objectSpace = Application.CreateObjectSpace<TaxRate>(null)) { 
            var taxRate = objectSpace.GetObjectsQuery<TaxRate>().FirstOrDefault(t => t.State == Customer.BillingAddressState); 
            if (taxRate != null) { 
                return TotalAmount * taxRate.Rate; 
            } 
        } 
        return 0; 
    } 
    

    Tip

    You can find an example on how to access business objects shared by the host from a tenant in our Outlook Inspired Demo on GitHub. Files to review:

    Important

    Host user interface mode does not support the following standard modules: Modules in a Multi-Tenant Application

    Shared Business Objects in Lookup and Calculated Properties

    • You can use shared business objects in calculated properties as operands in Free Joins. Specify a PersistentAliasAttribute.

      The following code sample uses the shared TaxRate object to calculate the Tax property value.

      [PersistentAlias("[<TaxRate>][State = ^.Customer.BillingAddressState].Single(Rate) * TotalAmount")] 
      public decimal Tax => EvaluateAlias<decimal>(); 
      
    • You can assign a shared type to a non-persistent reference property to display the shared business objects in the lookup property editor.

    Note

    If you use shared types with business object types in calculated or lookup properties, you must populate additional object spaces as described in the following method description: PopulateAdditionalObjectSpaces(XafApplication).

    Access Tenant Data from the Host

    The host has full access to tenant data. The host can use the following methods to obtain an Object Space for a specific tenant.

    var objectSpace = Application.CreateObjectSpace<Type>('tenantName'));
    

    Note

    To access tenant data, the tenant database must exist and be updated; you cannot access databases that are non-existent or uninitialized.

    Limitations

    • A shared type cannot be used in associations with regular business object types.
    • A shared type cannot be additionally registered as a regular business type.
    • Calculated properties based on shared types are not supported in Server, InstantFeedback, ServerView, and DataView list view data access modes.
    • Avoid obtaining the IServiceProvider instance from the ObjectSpace or Session instance used to access shared business objects, as services retrieved in this manner may function incorrectly.
    See Also