Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[2.0] Multi-Tenancy #666

Open
mottibec opened this issue Feb 18, 2020 · 5 comments
Open

[2.0] Multi-Tenancy #666

mottibec opened this issue Feb 18, 2020 · 5 comments
Milestone

Comments

@mottibec
Copy link

we are converting our RESTier server to a Multi-tenant server and I was wondering if RESTier has support for that.
is there a built-in way to register an EDM model per tenant?
and if not what would be the best way to approach this?

some background:
our RESTier servers are serving as middleware between our front-end apps and Microsoft CDS,
until now we supported only one CDS instance per server but now we must support a multi-tenant architecture

@robertmclaws
Copy link
Collaborator

This is a great question, unfortunately, I don't believe that Restier is abstracted enough to be able to address different EDM models at different URLs. Now, if it was the exact same data model, just different connection strings, I believe that would be possible. But the Model lookup routines in Restier are not ideal, and I ran into problems before when I had different data models under the same service. I can't recall if I fixed it or not.

Sorry if that is not more helpful.

@mottibec
Copy link
Author

mottibec commented Feb 19, 2020

after some trial and error I got the following startup code working, not sure if it works 100% yet

            var tenants = GetTenants();
            string currentTenantId = null;

            config.UseRestier<CdsApi>(services =>
            {
                var tenantId = currentTenantId;
                services.TryAddScoped(sp =>
                {
                    var id = tenantId;
                    return tenants.First(t => t.Id == id);
                });
            });

            foreach (var tenant in tenants)
            {
                currentTenantId = tenant.Id;
                config.MapRestier<CdsApi>($"restier{tenant.Name}", $"{tenant.Name}/api", true);
            }

and in the model builder

var svc = context.GetApiService<CdsApi>();
var tenant = svc.TenantInfo;
tenant.Entities ....

@robertmclaws
Copy link
Collaborator

Hey that looks like it could work! Sounds like what's going to be really important here is unit test coverage of the API... you should look at the unit tests here to see how we leverage a library I wrote called Breakdance to help test Restier methods. You will probably want to do something similar to make sure your tenant-based APIs are working.

Also, you'll want to make sure you're always using .FirstOrDefault() and then check for null, otherwise you might get a runtime exception on the API, and that would probably be bad for your customers.

HTH! 👊

@robertmclaws robertmclaws added this to the 2.0 milestone Dec 5, 2023
@robertmclaws
Copy link
Collaborator

Let's make sure we have at least one solid approach for multi-tenancy in Restier 2.0.

@robertmclaws robertmclaws changed the title multi-tenant architecture [2.0] Multi-Tenancy Dec 5, 2023
@rafaelbastos29
Copy link

Hello @robertmclaws,

I managed to configure the RESTier library to work with multitenant (different databases) in the following way:

1 - Creating a middleware to get from the api route the tenant identifier;
2 - When registering the api, adding to the dependency injection container the ability to access the http context, and configuring my DBContext by scope, being created using a delegate (Func<IServiceProvider, DBContext>). The delegate implementation will parse the HttpContext to determine which tenant the DBContext should be created on.
3 - Register an api route for each tenant, adding the tenant identifier to the route (which will be used in the middleware).

Apparently it worked correctly, let me know if this approach has been tested before, and if it can be considered safe.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: No status
Development

No branches or pull requests

3 participants