views:

561

answers:

1

Hi all,

I am creating an asp.net mvc web site and I need an advice. I have following layers:

  • database
  • data access layer (domain objects, DAO interfaces + DAO implementations based on a NHibernate)
  • service layer (service interfaces + service implementations)
  • presentation layer (ASP.NET MVC)

There are actually several databases:

  • one database with a common data and customers list
  • many databases - each database for one customer (with the same structure, but not necessery on the same server)

DAO's and services are "linked" in this way:

MyMainService (contains business logic)
  MyMainDao (contains data access functions)
    MyMainSessionFactory (session factory for the main database)
      MyMainDbProvider (db provider with a connection to the main database)

or:

MyCustomerService (contains business logic)
  MyCustomerDao (contains data access functions)
    MyCustomerSessionFactory (session factory for the customer database)
      MyCustomerDbProvider (db provider with a connection to the main database)

or mixed (using both databases at the same time):

MySuperService (contains business logic)
  MyMainDao (contains data access functions)
    MyMainSessionFactory (session factory for the main database)
      MyMainDbProvider (db provider with a connection to the main database)
  MyCustomerDao (contains data access functions)
    MyCustomerSessionFactory (session factory for the customer database)
      MyCustomerDbProvider (db provider with a connection to the main database)

I am using property placeholders (and the PropertyPlaceholderConfigurer) in both providers.

And here we came to the point where I want to use this services (in a ASP.NET MVC controller):

There is no problem if I want to use MyMainService - I use DI and everything works fine.

But if I want to use MyCustomerService or MySuperService I don't think that I can use DI, but more "dependency pull". I think that I should create some kind of a "service factory" to which I will pass a customer ID and the service factory will return me the service with the connection to the appropriate database. Something like:

TService GetService<TService>(int customerId)
{
  CustomerInfo info = GetCustomerInfo(customerId);
  IConfigurableApplicationContext context = (IConfigurableApplicationContext)WebApplicationContext.GetRootContext();
  PropertyPlaceholderConfigurer conf = (PropertyPlaceholderConfigurer)context.GetObject("PropertyPlaceholderConfigurer");
  conf.Properties["db.datasource"] = info.DataSource;
  conf.Properties["db.user"] = info.UserName;
  conf.Properties["db.password"] = info.Password;
  conf.Properties["db.database"] = info.DatabaseName;
  context.AddObjectFactoryPostProcessor(conf);
  context.Refresh();
  IEnumerator it = context.GetObjectsOfType(typeof(TService)).Values.GetEnumerator();
  if (it.MoveNext())
  {
    return (TService)it.Current;
  }
}

Is this the right way or am I completely wrong and I should do this some other way?

Note: There will be a case when I will want to use the same service for different customers at the same time, for example:

  IMyService s1 = GetService<IMyService>(1);
  IMyService s2 = GetService<IMyService>(2);
  s1.importData(s2.exportData());

Any advice would be appreciated.

Many thanks!

A: 

In the "MySuperService", you use both beans (MyMainDao and MyCustomerDao). This works since they have different types (Java classes).

If you want a factory which can return either, use the same approach as in "MySuperService" but instead of relying on the type, give the two beans different names. That way, your factory can look them up by name and you can say:

connector = factory.lookup("name");
Aaron Digulla
I am not sure what you mean. Can you please describe it a little more? Thanks!
rrejc
See my edits (err ... complete rewrite :)
Aaron Digulla