NHIbernate SessionFactory and Configuration Recreation - asp.net-mvc-3

I have one difficult situation.
As we know NH SessionFactory is a singleton in our app.
"Heavyweight, thread-safe, and you only should ever have one per
database".
And SessionFactory is created from Configuration().BuildSessionFactory() where Configuration() is my fluently configured database.
Here is the poblem.
I need to use different users for my connection string in an MVC app. This is needed to connect to the database by different users. When connection is ok, then I use NH to manipulate domain mapped objects.
Question here is how to pass different users to Configuration and use this SessionFactory in case when we need create Configuration first of all? Creating the SessionFactory again is a wrong way, right?
And this becomes more harder because I use Windsor container to register all objects before my MVC app's run.

It sounds like you are wanting to provide a different connection string for different users of your application.
NHibernate has a feature in which you can provide your own DriverConnectionProvider which will allow you to ultimately be able to create custom connection strings on the fly by overriding the GetConnection() method.
Example:
class DynamicConnectionProvider : DriverConnectionProvider
{
public override IDbConnection GetConnection()
{
IDbConnection connection = Driver.CreateConnection();
try
{
connection.ConnectionString = // Add your logic for dynamically creating a connection string
connection.Open();
}
catch ( Exception e )
{
connection.Dispose();
throw;
}
return connection;
}
}
You can also take a look at the following links for examples:
https://stackoverflow.com/a/2927967/670028
http://nhforge.org/blogs/nhibernate/archive/2008/09/18/extending-nhibernate-s-driverconnectionprovider.aspx
And yes, creating duplicate SessionFactories would be quite costly to your applications memory usage, would complicate your applications architecture, and is really unnecessary as there are other options such as the one I listed above.

Related

Spring service with in-memory list

I want to have a service which keeps a list inmemory so I don't need to access the database everytime. The service is accessed by a controller. Is this a valid approach or am I missing something? What about concurrent access here (from the controller)? Is this (stateful service) an anti-pattern?
#Service
public class ServiceCached {
private List<SomeObject> someObjects;
#PostConstruct
public void initOnce() {
someObjects = /** longer running loading methodd **/
}
public List<SomeObject> retrieveObjects() {
return someObjects;
}
}
Thanks!
I wouldn't call it an anti-pattern, but in my opinion loading the list from the database in a #PostConstruct method is not a good idea as you slow down the start up of your application, I'd rather use a lazy loading mechanism, but this would potentially introduce some concurrent access issues that would need to be handled.
In your example concurrent access from the controller should not be a problem as the list is loaded from a #PostConstruct method and the controller would depend on this service, therefore this service would need to be fully constructed before it is injected into the controller, therefore the list would already be loaded.
Preferably I'd suggest using Spring Caching: Caching Data with Spring, Documentation, Useful guide
Usage example:
#Cacheable("books")
public Book getByIsbn(String isbn) {
simulateSlowService();
return new Book(isbn, "Some book");
}
This way you do not need to take care of loading and evicting the objects. Once set up, the caching framework will take care of this for you.

how can I have a datasource object that is not a bean in spring?

This might sound weird. But I want to know how/if I can create datasource objects during runtime and not when the container start-up.
Here is the problem I am working on:
I have a MySql database which stores the URL, userName and password for other SQL Servers that I need to connect and do overnight processing. This list of SQL Servers changes everytime. so it cannot be hard-coded in properties files. Further, the no of SQL servers is about 5000 or more.
The business logic involves reading the MySQL database (which is currently a datasource bean created during container start-up) and for each entry in SQL_SERVER_MAPPING table in MySQL database, I need to connect to that database and run reports.
I was thinking of doing something along this line for each of the SQL server instances
public DataSource getdataSource(String url, String u, String p, String class) {
return DataSourceBuilder
.create()
.username(u)
.password(p)
.url(url)
.driverClassName(class)
.build();
}
public JdbcTemplate jdbcTemplate(DataSource datasource) {
return new JdbcTemplate(dataSource);
}
Here is a builder that generates datasource for a given url and create the necessary jdbcTemplate from it. so basically create one for each of SQL server configurations.
My concern is I will be creating about 5000 datasources and 5000 jdbcTemplate or perhaps even more. That doesn't sound right to me. what is the right way to get around here?
is there a way to remove datasource objects as soon I am done with it or recycle them?
should I cache these dataSource objects in my Spring application, so I dont have to create one each time and discard it. but this implies, I need to cache 5000 (or probably more in the future).
Spring docs says
The DataSource should always be configured as a bean in the Spring IoC container. In the first case the bean is given to the service directly; in the second case it is given to the prepared template.
so that makes things harder for me.
Thanks
You can define a bean myBean with scope prototype and use the getBean(String name, Object... args) method of a BeanFactory. args would be the args sent to the constructor (in your case these would be db connections). The bean would return a jdbcTemplate constructed with a datasource defined from the connection properties. This template can be further used in other classes.
Since the scope of the bean is prototype, the created instances will be garbaged collected after the current object is used. This can help if you have memory constraints, the really heavy lifting in terms of creating objects is done when getting the actual DB connections. Caching would be a good solution in case of heavy re-usage of connections.
See an example of this bean and method usage here: spring bean with dynamic constructor value

two datasource in Spring integration inbound channel

I am using int-jdbc:inbound-channel-adapter of Spring Integration.
My Query is how to use two different datasource i.e. datasource A for querying and datasource B for update , in a single adapter?
You cannot; the same JdbcTemplate is used for both operations; you can omit the update query and do the update on an outbound channel adapter.
In Spring JDBC module we have something like AbstractRoutingDataSource.
Which you can implement based on some ThreadLocal variable.
From other side the JdbcPollingChannelAdapter has code like this:
private Object poll() {
List<?> payload = doPoll(this.sqlQueryParameterSource);
...
executeUpdateQuery(payload);
return payload;
}
So, you should somehow to hook in between doPoll() and executeUpdateQuery and, therefore, change the key in the ThreadLocal to be able to switch to another DataSource in the AbstractRoutingDataSource.
I only the hack like custom sqlParameterSourceFactory.createParameterSource() and the ThreadLocal modification there. Just because the code is like:
private void executeUpdateQuery(Object obj) {
SqlParameterSource updateParamaterSource = this.sqlParameterSourceFactory.createParameterSource(obj);
this.jdbcOperations.update(this.updateSql, updateParamaterSource);
}
(Will commit the fix for updateParamaterSource typo soon :-)).
But! As Gary mentioned in his answer, it would be better to have several JDBC adapters for different DataSources : one for SELECT and another for UPDATE. Both of them may work in the same XA Transaction (<transactional> on the <poller>). And from there we really differentiate the business logic and level of responsibility.

Membership reboot replace Ninject with Simple Injector

I need add membership reboot (RavenDb) into the project that use IOC Simple Injector
Ninject implementation
var config = MembershipRebootConfig.Create();
kernel.Bind<MembershipRebootConfiguration<HierarchicalUserAccount>>().ToConstant(config);
kernel.Bind<UserAccountService<HierarchicalUserAccount>>().ToSelf(); kernel.Bind<AuthenticationService<HierarchicalUserAccount().To<SamAuthenticationService<HierarchicalUserAccount>>();
kernel.Bind<IUserAccountRepository<HierarchicalUserAccount>>().ToMethod(ctx => new BrockAllen.MembershipReboot.RavenDb.RavenUserAccountRepository("RavenDb"));
kernel.Bind<IUserAccountQuery>().ToMethod(ctx => new BrockAllen.MembershipReboot.RavenDb.RavenUserAccountRepository("RavenDb"));
Simple Injector implementation
container.Register(MembershipRebootConfig.Create);
container.Register<UserAccountService<HierarchicalUserAccount>>();
container.Register<AuthenticationService<HierarchicalUserAccount>, SamAuthenticationService<HierarchicalUserAccount>>();
container.Register<IUserAccountRepository<HierarchicalUserAccount>>(() => new RavenUserAccountRepository("RavenDb"), Lifestyle.Singleton);
container.Register<IUserAccountQuery>(() => new RavenUserAccountRepository("RavenDb"));
On row
container.Register<UserAccountService<HierarchicalUserAccount>>();
I have an error
For the container to be able to create UserAccountService, it should contain exactly one public constructor, but it has 2.
Parameter name: TConcrete
Thanks for your help.
Simple Injector forces you to let your components to have one single public constructor, because having multiple injection constructors is an anti-pattern.
In case the UserAccountService is part of your code base, you should remove the constructor that should not be used for auto-wiring.
In case the UserAccountService is part of a reusable library, you should prevent using your container's auto-wiring capabilities in that case as described here. In that case you should fallback to wiring the type yourself and let your code call into the proper constructor, for instance:
container.Register<UserAccountService<HierarchicalUserAccount>>(() =>
new UserAccountService<HierarchicalUserAccount>(
container.GetInstance<MembershipRebootConfiguration<HierarchicalUserAccount>>(),
container.GetInstance<IUserAccountRepository<HierarchicalUserAccount>>()));
I'm just going to include here how I converted the Ninject configuration to Simple Injector for the Single Tenant sample in the MembershipReboot repository (which I cloned). I thought that might be beneficial for anyone who was searching for how to go about this, as it may save them some time.
Firstly, the configuration in the Single Tenant sample's NinjectWebCommon class is:
var config = MembershipRebootConfig.Create();
kernel.Bind<MembershipRebootConfiguration>().ToConstant(config);
kernel.Bind<DefaultMembershipRebootDatabase>().ToSelf();
kernel.Bind<UserAccountService>().ToSelf();
kernel.Bind<AuthenticationService>().To<SamAuthenticationService>();
kernel.Bind<IUserAccountQuery>().To<DefaultUserAccountRepository>().InRequestScope();
kernel.Bind<IUserAccountRepository>().To<DefaultUserAccountRepository>().InRequestScope();
Now, I'll set out the whole SimpleInjectorInitializer class, which started with the one which was added to the project via the SimpleInjector.MVC3 Nuget package, and follow up with comments:
public static class SimpleInjectorInitializer
{
/// <summary>Initialize the container and register it as MVC3 Dependency Resolver.</summary>
public static void Initialize()
{
var container = new Container();
container.Options.DefaultScopedLifestyle = new WebRequestLifestyle();
container.RegisterMvcControllers(Assembly.GetExecutingAssembly());
InitializeContainer(container);
container.Verify();
DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));
}
private static void InitializeContainer(Container container)
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<DefaultMembershipRebootDatabase, BrockAllen.MembershipReboot.Ef.Migrations.Configuration>());
var config = MembershipRebootConfig.Create();
container.Register(() => config, Lifestyle.Singleton);
container.Register(() => new DefaultMembershipRebootDatabase(), Lifestyle.Scoped);
container.Register<IUserAccountQuery, DefaultUserAccountRepository>(Lifestyle.Scoped); // per request scope. See DefaultScopedLifestyle setting of container above.
container.Register<IUserAccountRepository, DefaultUserAccountRepository>(Lifestyle.Scoped);
container.Register(() => new UserAccountService(container.GetInstance<MembershipRebootConfiguration>(), container.GetInstance<IUserAccountRepository>()));
container.Register<AuthenticationService, SamAuthenticationService>();
var iUserAccountQueryRegistration = container.GetRegistration(typeof(IUserAccountQuery)).Registration;
var iUserAccountRepositoryRegistration = container.GetRegistration(typeof(IUserAccountRepository)).Registration;
iUserAccountQueryRegistration.SuppressDiagnosticWarning(DiagnosticType.TornLifestyle, "Intend for separate Objects");
iUserAccountRepositoryRegistration.SuppressDiagnosticWarning(DiagnosticType.TornLifestyle, "Intend for separate Objects");
}
}
Scoping the config to a Singleton with a factory func is pretty much the same as Ninject's ToConstant.
DefaultMembershipRebootDatabase is the obvious departure, but I honestly don't think it matters whether MR's DefaultMembershipRebootDatabase is scoped a transient or per web request. It calls SaveChanges every time an operation is performed e.g. Registering a user. It does not use larger, per request-bound tansactions. So, using the same DefaultMembershipRebootDatabase context later in the same request is no going to cause any weird MR issues.
HOWEVER, some thought will need to given to what happens if you want to create a Domain User during the same operation as you create a MR UserAccount. (A Domain User may contain more information beyond password stuff, like first and last names, DOB etc.). Tying an MR UserAccount to a Domain User (with additional user info such a name, address etc.) is a common use case. So what happens if the creation of the Domain User fails after creation of the MR UserAccount succeeded? I don't know. Perhaps as part of the rollback, you delete the MR user. But the registration email will already have been sent. So, these are the issues that you face here.
As you can see, in the Simple Tenant sample, Brock registers both IUserAccountRepository and IUserAccountQuery to DefaultUserAccountRepository. This is obviously by design and so we have to do that as well, if we want to use MR's UserAccountService and AuthenticationService. Thus, we need to suppress the Diagnostic warnings which would otherwise prevent the Container from Verifying.
Hope that all helps and by all means let me know if there are problems with my registrations.
Cheers

mvc3 and linq to sql architecture

I am building an MVC3 application and I am using Linq to sql for my DAL. My DAL is called MyDataReader and handles creating/initializing datacontext, plus it defines all the methods that retrieve data from the database. All the methods are instance methods, so in order to call the methods, I need to instantiate a MyDataReader object.
My questions is: what is the best way to call the methods in my DAL. Initially, I was instantiating a MyDataReader object from the controllers whenever I needed to call a DAL method. Then I realized every time I instantiate a MyDataReader object, the datacontext object is created and a connection gets established.
In my second approach, I created a static parameter in the Global.asax file as:
public class MvcApplication : System.Web.HttpApplication
{
public static MyDataReader reader;
protected void Application_Start()
{
reader = new MyDataReader();
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
}
This limits the database initialization operation to minimum. I can call the DAL methods from all my controllers by:
MvcApplication.reader.CallTheMethod()
Is this a good way? What is the best way to call DAL methods?
No, this is the absolute worst way to do it. The biggest reason is that static objects are shared between all concurrent users. That means multiple users adding, removing, querying the same context. This is a recipe for disaster, and will probably cause data corruption.
The other problem is that data contexts are designed to be short lived, so they do not manage their internal caches and lists, they just assume you will dispose of them when you are done with an operation.
You do not need to worry about connection management. Internally, this is managed in a connection pool, and .net will automatically reuse connections and dispose of them when they are idle for a period of time.
Don't pre-maturely optimize. You are usually wrong.

Resources