NHibernate - using tenant specific table prefixes - nhibernate

We are developing a multi-tenant application using NHibernate where all tenants share the same database.
One option we considered was to use a tenant specific prefix for our database objects (I believe this the same approach taken by Orchard).
This would at least give us some kind of recovery model for tenant data and would mean we wouldn't have to include a tenantid filter on most of our queries.
So my question - has anyone employed this strategy? If so, how did you go about it.
Specifically, can we use the same SessionFactory for all tenants and can we use NHibernate to generate a new set of tables for a "new" tenant at runtime (is it safe to do so).
Thanks
Ben
[Update]
This was a worthwhile investigation but ultimately we decided that a shared schema was more suitable for our needs. Schema per tenant clearly offers better separation of tenant data but makes maintenance more difficult. Since our tenants are only storing small amounts of data, the thought of having 10 tables * 1K tenants is a little off-putting.

There are a couple of points of customization / extension that you may want to consider.
I don't think that you will be able to share the same session factory across tenants. I think that the simplest thing to do may be to update the mappings based on the tenant associated with the session factory.
public class EntitytMap:ClassMap<Entity>
{
public EntitytMap()
{
Table("TableName");
Schema(Session.TenantName);
Id(p => p.Id, "Id").GeneratedBy.Identity();
If you want to have each tenant in their own schema, this should work. If you want to keep the schema the same but have a prefix on the table, you could change to:
public class EntityMap:ClassMap<Entity>
{
public EntityMap()
{
Table(Session.TenantPrefix + "TableName");
Schema("SCHEMA");
Id(p => p.Id, "Id").GeneratedBy.Identity();
You can also try providing your own ConnectionProvider. Derive a class from NHibernate.Connection.DriverConnectionProvider and reference your own copy in the nhibernate configuration file instead of:
<property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
use
<property name="connection.provider">My.Project.DAL.NHibernate.CustomConnectionProvider, My.Project.DAL</property>
When the GetConnection provider is called, you can specify your own connection string based on the tenent.

can we use NHibernate to generate a new set of tables for a "new" tenant
at runtime (is it safe to do so)
I'd suggest that you wouldn't want to grant your web application the level of permissions required to perform these DDL tasks. I'd leave the web app with the minimum level of permissions for normal DML operations and have a background service operating as a 'Provisioning Service'. Its role would be schema modifications for the new tenant, and it is also a good place to put any other tenant provisioning tasks such as creating new folders, configuring IIS etc. All these tasks take time too and are best not done in a single web request. The background database can update a provisioning table, updating it with information about its progress until its complete and the web ui moves to the next step.

Related

Change the connection string dynamically (per request) on Entity Framework 7 / MVC 6

I have a MVC 6 application on which I need to connect to a different database (i.e. physical file but same schema) depending on who is accessing to it.
That is: each customer of the web application will have it's data isolated in an SQL database (on Azure, with different performances, price levels, etc.) but all those databases will share the same relational schema and of course, the Entity Framework context class.
var cadConexion = #"Server=(localdb)\mssqllocaldb;Database=DBforCustomer1;Trusted_Connection=True;";
services.AddEntityFramework().AddSqlServer().AddDbContext<DAL.ContextoBD>(options => options.UseSqlServer(cadConexion));
The problem is that if I register the service this way I've tied it to a concrete database for a concrete customer, and I don't know if I can change latter when the middleware execution starts (this would be a good point as I can know then who is ringing at the door).
I know I can construct the Database Context passing the connection string as a parameter but this would imply that I should be creating the Database Context at runtime (early in the pipeline) for every request adn I don't know if this could be potentially unefficient or a bad practice. Furthermore I think this way I can't register the Database Context as a service for injecting it on my controllers...
What is the correct approach for this? Anybody has a similar configuration working on production?
Thanks in advance
I would have preferred not to answer my own question, but I feel that I must offer guidance to those with a similar problem, after a long and deep research over internet so I can save them a lot of time testing multi-connection scenarios, wich is quite laborious...
I've finally used a (very recent) feature and APIs of Azure called "Elastic Database Tools" wich, to be concise, is a set of tools from Microsoft aimed to address this concrete problem, specially for SaaS (software as a service) scenarios (as mine is).
Here is a good link to start with:
https://azure.microsoft.com/en-us/documentation/articles/sql-database-elastic-scale-get-started/
Good luck with your projects!
First of all, I do not recommend swapping connection strings per request.
But that's not the question. You can do this. You will need to pass your DbContext a new connection string.
.AddDbContext caches the connection string in the dependency injection container, so you cannot use DI to make this scenario work. Instead, you will need to instantiate your DbContext yourself and pass it a new connection string.

How to develop Multi tenant application using Castle windsor fluent nhibernate and MVC4

I am new to Castle Windsor and Fluent NHibernate (AutoMapping).
I am currently working on multi Tenant application and have following requirement.
Master Database to store tenant information
Database per tenant
I have integrated the persistence facility using castle Windsor and I am able to access the Master Database. I am getting stuck where in I want to get the connection info for the tenant from the master Db, pass this information to the persistence facility again to build new session. So, eventually can have access to master db and tenant specific Db.
Can any one guide me how can I proceed on this.
In short:
On user log in, I want to validate the user and identify its tenant Database connection string from master db and use this info to build new session for tenant specific db operations.
I would create 2 derived classes from ISession: IMasterSession and ITenantSession.
This allows you to easily refer to either database from your controllers or view models.
You will need to make two registrations for ISessionFactory 1 for your master database and 1 for your tenant database. Name these so that you can refer to these.
Now register IMasterSession as follows:
Component.For<ISession>().PerWebRequest().Named("masterSession").UsingFactoryMethod((k, m) =>
{
var masterFactory = k.Resolve<ISessionFactory>("masterSessionFactory");
return masterFactory.OpenSession();
}),
Component.For<object>().Forward<IMasterSession>().Proxy.MixIns(registration =>
registration.Component("masterSession"))
The session factories must be registered with lifestyle singleton, since you will only need one in your application. The lifetime of your session will depend on the kind of application you are making, probably PerWebRequest.
There might be a better way to do this, and I would love to hear that.
The approach for the tenant database should similar. However you would either need to use the overload of OpenSession that takes a IDBConnection or Implement a custom connection provider. You can find more about that here
I hope this helps.
Kind regards,
Marwijn.

Where to put NHibernate query logic?

I am trying to set up proper domain architecture using Fluent NHibernate and Linq to NHibernate. I have my controllers calling my Repository classes, which do the NHibernate thang under the hood and pass back ICollections of data. This seems to work well because it abstracts the data access and keeps the NHibernate functionality in the "fine print".
However, now I'm finding situations where my controllers need to use the same data calls in a different context. For example, my repo returns a list of Users. That's great when I want to display a list of users, but when I want to start utilizing the child classes to show roles, etc., I run into SELECT N+1 issues. I know how to change that in NHibernate so it uses joins instead, but my specific question is WHERE do I put this logic? I don't want every GetAllUsers() call to return the roles also, but I do want some of them to.
So here are my three options that I see:
Change the setting in my mapping so the roles are joined to my query.
Create two Repository calls - GetAllUsers() and GetUsersAndRoles().
Return my IQueryable object from the Repository to the Controller and use the NHibernate Expand method.
Sorry if I didn't explain this very well. I'm just jumping into DDD and a lot of this terminology is still new to me. Thanks!
As lomaxx points out, you need query.Expand.
To prevent your repository from becoming obscured with all kinds of methods for every possible situation, you could create Query Objects which make configurable queries.
I posted some examples using the ICriteria API on my blog. The ICriteria API has FetchMode instead of Expand, but the idea is the same.
I try and keep all the query logic in my repositories and try to only pass back the ICollection from them.
In your situation, I'd pass in some parameters to determine if you want to eager load roles or not and construct the IQueryable that way. For example:
GetAllUsers(bool loadRoles)
{
var query = session.Linq<Users>();
if(loadRoles)
query.Expand("Roles");
return query.ToList();
}
I would choose 2, creating two repositories. And perhaps would I consider creating another repository call to GetRoleByUser(User user). So, you could access a user's role upon user selection change on a seperate thread, if required, so it would increment your performance and won't load every user's roles for each of your users, which would require most resources.
It sounds like you are asking if it is possible to make GetAllUsers() sometimes return just the Users entities and sometimes return the Users and the roles.
I would either make a separate repository method called GetRolesForUser(User user), use lazy loading for Roles, or use the GetAllUsers(bool loadRoles) mentioned by lomaxx's answer.
I would lean toward lazy loading roles or a separate method in your repository.

Best way to share data between .NET application instance?

I have create WCF Service (host on Windows Service) on load balance server. Each of this service instance maintain list of current user. E.g. Instance A has user A001, A002, A005, instance B has user A003, A004, A008 and so on.
On each service has interface that use to get user list, I expect this method to return all user in all service instance. E.g. get user list from instance A or instance B will return A001, A002, A003, A004, A005 and A008.
Currently I think that I will store the list of current users on database but this list seem to update so often.
I want to know, is it has another way to share data between WCF service that suit my situation?
Personally, the database option sounds like overkill to me just based on the notion of storing current users. If you are actually storing more than that, then using a database may make sense. But assuming you simply want a list of current users from both instances of your WCF service, I would use an in-memory solution, something like a static generic dictionary. As long as the services can be uniquely identified, I'd use the unique service ID as the key into the dictionary and just pair each key with a generic list of user names (or some appropriate user data structure) for that service. Something like:
private static Dictionary<Guid, List<string>> _currentUsers;
Since this dictionary would be shared between two WCF services, you'll need to synchronize access to it. Here's an example.
public class MyWCFService : IMyWCFService
{
private static Dictionary<Guid, List<string>> _currentUsers =
new Dictionary<Guid, List<string>>();
private void AddUser(Guid serviceID, string userName)
{
// Synchronize access to the collection via the SyncRoot property.
lock (((ICollection)_currentUsers).SyncRoot)
{
// Check if the service's ID has already been added.
if (!_currentUsers.ContainsKey(serviceID))
{
_currentUsers[serviceID] = new List<string>();
}
// Make sure to only store the user name once for each service.
if (!_currentUsers[serviceID].Contains(userName))
{
_currentUsers[serviceID].Add(userName);
}
}
}
private void RemoveUser(Guid serviceID, string userName)
{
// Synchronize access to the collection via the SyncRoot property.
lock (((ICollection)_currentUsers).SyncRoot)
{
// Check if the service's ID has already been added.
if (_currentUsers.ContainsKey(serviceID))
{
// See if the user name exists.
if (_currentUsers[serviceID].Contains(userName))
{
_currentUsers[serviceID].Remove(userName);
}
}
}
}
}
Given that you don't want users listed twice for a specific service, it would probably make sense to replace the List<string> with HashSet<string>.
A database would seem to offer a persistent store which may be useful or important for your application. In addition it supports transactions etc which may be useful to you. Lots of updates could be a performance problem, but it depends on the exact numbers, what the query patterns are, database engine used, locality etc.
An alternative to this option might be some sort of in-memory caching server like memcached. Whilst this can be shared and accessed in a similar (sort of) way to a database server there are some caveats. Firstly, these platforms are generally not backed by some sort of permanent storage. What happens when the memcached server dies? Second they may not be ACID-compliant enough for your use. What happens under load in terms of additions and updates?
I like the in memory way. Actually I am designing a same mechanism for one my projects I'm working now. This is good for scenarios where you don't have opportunities to access database or some people are really reluctant to create a table to store simple info like a list of users against a machine name.
Only update I'd do there is a node will only return the list of its available users to its peer and peer will combine that with its existing list. Then return its existing list to the peer who called. Thats how all the peers would be in sync with same list.
The DB option sounds good. If there are no performance issues it is a simple design that should work. If you can afford to be semi realtime and non persistent one way would be to maintain the list in memory in each service and then each service updates the other when a new user joins. This can be done as some kind of broadcast via a centralised service or using msmq etc.
If you reconsider and host using IIS you will find that with a single line in a config file you can make the ASP Global, Application and Session objects available. This trick is also very handy because it means you can share session state between an ASP application and a WCF service.

Where is the session located ? in client browser or at the server side ? and why it is used in hibernate?

I know that the session is used for the database in Hibernate, but what is the task of the session in database?
Does anyone know about this?
Update:
Apologies, my links are to Java APIs (must have missed the nhibernate tag). Regardless, there will be more than one type of session for .NET also.
There will typically be more than one type of session:
The HttpSession is a server-side object:
Provides a way to identify a user
across more than one page request or
visit to a Web site and to store
information about that user.
The hibernate Session is also a server-side object:
The lifecycle of a Session is bounded
by the beginning and end of a logical
transaction. (Long transactions might
span several database transactions.)
The main function of the Session is to
offer create, read and delete
operations for instances of mapped
entity classes.
The session is server side, if by server side you mean as in the web application or client/server application sense.
It is an implementation of the Unit of Work pattern, and does stuff like keeping track of which entities that have been changed, caching of entities and making sure that a specific entity is represented by only one actual instance in the scope of the session.
The NHibernate docs describe ISession like this:
A single-threaded, short-lived object
representing a conversation between
the application and the persistent
store. Wraps an ADO.NET connection.
Factory for ITransaction. Holds a
mandatory (first-level) cache of
persistent objects, used when
navigating the object graph or looking
up objects by identifier.