问题
I have the following SessionFactory for Fluent NHibernate.
I am getting an error of
An invalid or incomplete configuration was used while creating a SessionFactory.
with an InnerException of
An item with the same key has already been added.
This problem is only happening occasionally and my application works fine most of the time.
Based on NHibernate: System.Argument Exception : An item with the same key has already been added I'm guessing my class is not thread-safe which would explain the intermittent nature of this error.
using System;
using NHibernate;
using NHibernate.Cache;
using NHibernate.Cfg;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using WSS.Data.Domain;
namespace WSS.Data {
public static class SessionFactory {
private static ISessionFactory _factory = null;
private static ISessionFactory GetFactory() {
if (_factory == null) {
NHibernate.Cfg.Configuration config;
config = new NHibernate.Cfg.Configuration();
config.Configure();
if (config == null) {
throw new InvalidOperationException("NHibernate configuration is null.");
}
config.AddAssembly("WSS.Data");
_factory = config.BuildSessionFactory();
if (_factory == null) {
throw new InvalidOperationException("Call to Configuration.BuildSessionFactory() returned null.");
}
}
return _factory;
}
private static ISessionFactory GetFluentFactory() {
if(_factory == null) {
_factory = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2000
.ConnectionString(c => c
.Is(ConnectionStrings.Auto))
.Cache(c => c
.UseQueryCache()
.ProviderClass())
.ShowSql())
.Mappings(m => m
.FluentMappings.AddFromAssemblyOf())
.BuildSessionFactory();
}
return _factory;
}
public static ISession OpenSession() {
ISession session;
session = GetFluentFactory().OpenSession();
if (session == null) {
throw new InvalidOperationException("Call to factory.OpenSession() returned null.");
}
return session;
}
}
}
回答1:
The usual approach is to create a mutex (probably in your public method) that only allows single access. See http://msdn.microsoft.com/en-us/library/system.threading.mutex.aspx
Not tested as compiling, but something like:
private static Mutex _sessionMutex = new Mutex();
public static ISession OpenSession() {
ISession session;
_sessionMutex.WaitOne();
session = GetFluentFactory().OpenSession();
if (session == null) {
throw new InvalidOperationException("Call to factory.OpenSession() returned null.");
}
_sessionMutex.ReleaseMutex();
return session;
}
来源:https://stackoverflow.com/questions/5353192/how-to-make-this-thread-safe