Accessing Other Tenant’s Data in an Application

Developer Network

Forums, blogs, and downloads for SaaSGrid developers.

Accessing Other Tenant’s Data in an Application

  • Comments 1

Consider the following use cases:

  • My application permits tenants to create events, and I want to publish a list of all of those events in another location.
  • I want tenants to be able to mark data as sharable so it can be viewed by other tenants.

SaaSGrid's built-in Tenant and Provider Contexts', in conjunction with a concept called "impersonation", provides a mechanism that can be used to access data for any and all tenants of an application. This article will discuss how this can be done and presents a basic example that involves modifying the existing Taskr sample application.

Introduction to the Tenant and Provider Context

Before getting started, let's review and compare the Tenant and Provider Context:

Tenant Context

Provider Context

  • Provides information about the tenant that the application's logged in user belongs to
  • Automatically established
  • Database queries done only apply to data pertaining to the appropriate tenant
  • Provides information about the provider of the application currently being used
  • Manually established
  • Database queries done apply to all data pertaining to the application (all tenant's data)

Note: In addition to the Tenant and Provider Contexts', there is also Session, Request, User, and Subscription Contexts' that will not be discussed further here but may be helpful when developing your application. Please consult the SaaSGrid Developer Guide for additional information.

Using the Provider Context to Get Application Data

All database queries done within an instance of the Provider Context apply to all of an application's data. See the code snippet below to see an example of creating and using the provider context.

Sample Provider Context Usage

using (ProviderContext providerContext =

    ProviderContext.NewProviderContext())

{

    // Data queries here execute for all application

    // data - not just the current user's tenant.

} 

"Wrapping" database calls as shown above is essentially all that is required to do basic operations that pertain to all data in the system. This approach does have some limitations pertaining to data retrieval:

  • No information is returned pertaining to the tenant of each data item. For example, if I have a database query that returns a list of all tasks, there is no way to tell which task corresponds to which tenant. (This is addressed in the next section.)
  • When developing locally, there will be no difference in the data returned. This is because the database that you are using locally by design contains a single tenant's data.

In the next section, we'll take a look at another approach that allows you to retrieve data while knowing which tenant created it. This is enabled with a concept called "context impersonation."

Context Impersonation

It is possible to nest the Tenant and Provider Contexts within one another to affect the scope of a command being executed, much like the stack available within a traditional programming language. The diagram below shows how the scope of commands are changed as the application developer manually instantiates various Tenant and Provider contexts.

 

The following code example shows how to use context impersonation to perform data retrieval for all of a provider's data while having access to information about the tenant that created it.

Sample Context Impersonation

using (ProviderContext providerContext =

    ProviderContext.NewProviderContext())

{

    IList<ITenantProfile> customers =

        providerContext.GetCustomers();

    foreach (var customer in customers)

    {

        using (TenantContext tenantContext =

            TenantContext.NewTenantContext(customer.ID))

        {

            // Data queries here execute for the

            // designated tenant. You can link

            // the tenant information to the data this way.

        }

    }

}

 

Warning: This specific code example could take a very long time if your application has many customers. You'll probably want to consider calling code that loops through every tenant sparingly due to the performance implications.

Please also note that we are cognizant of the anticipated need to include tenant data, or some means of linking rows with tenant information, for data returned from queries executed in a provider context. We're looking to include this in a future release of SaaSGrid, thus eliminating the need to loop through each tenant.

Live Example

We produced an additional sample that demonstrates usage of the Provider and Tenant Context. We took the "Taskr with Linq" example, and added an additional view beneath the task list showing all of the tasks from other companies, as depicted in the screenshot below.

 

An additional method on the Taskr Core service was implemented to return the data for this grid, whose code is shown below. As you can see, this loops through each and every tenant and builds the list of tasks that should be displayed on the grid.

Taskr Service Addition

Guid myTenantId = TenantContext.Current.GetCompanyProfile().Id;

IList<TaskFromOtherDTO> tasks = new List<TaskFromOtherDTO>();

 

using (ProviderContext providerContext =

    ProviderContext.NewProviderContext())

{

    IList<ITenantProfile> customers = providerContext.GetCustomers();

    foreach (var customer in customers)

    {

        if (!customer.Id.Equals(myTenantId))

        {

            using (TenantContext tenantContext =

                TenantContext.NewTenantContext(customer.Id))

            {

                TaskrDataContext db = new TaskrDataContext(

                    ConfigurationProvider.GetConnection("Taskr"));

                foreach (var task in db.Tasks.OrderBy(t => t.DueDate))

                {

                    tasks.Add(TaskFromOtherDTO.StaticMapFrom(

                        task, customer.Name));

                }

            }

        }

    }

}

 

return tasks;

You can download the full sample of this special Taskr version from our download area by clicking here.

Of course, as always, please post a comment to this article or post in our developer center if you have any questions or feedback.

  • It has been noted that this solution will only work if the Tenant Portal application's database is housed on one database (which is typically the case anyway). This is correct as the Provider Context has limited support at this time. (Data operations done with the Provider Context operate correctly on single database, co-mingled applications only at this time.)

Page 1 of 1 (1 items)