I'm getting the infamous "Error activating XYZ. No matching bindings are available blah blah blah" from Ninject 3.0.1.10 in an ASP.NET MVC project.
The following is how I've setup my binding (very simple):
public static class NinjectWebCommon
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
/// <summary>
/// Starts the application
/// </summary>
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
bootstrapper.Initialize(CreateKernel);
}
/// <summary>
/// Stops the application.
/// </summary>
public static void Stop()
{
bootstrapper.ShutDown();
}
/// <summary>
/// Creates the kernel that will manage your application.
/// </summary>
/// <returns>The created kernel.</returns>
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
return kernel;
}
private static void RegisterServices(IKernel kernel)
{
string connectionString = WebConfigurationManager.ConnectionStrings["STAGING"].ConnectionString;
kernel.Bind<IUserAccountRepository>()
.To<SqlUserAccountRepository>()
.WithConstructorArgument("connectionString", connectionString);
kernel.Bind<IRecipeRepository>()
.To<SqlRecipeRepository>()
.WithConstructorArgument("connectionString", connectionString);
kernel.Bind<HomeViewModel>().ToSelf();
}
}
When the controller Index action is invoked it attempts to create a HomeViewModel object as such:
public ActionResult Index()
{
IKernel kernel = new StandardKernel();
HomeViewModel model = kernel.Get<HomeViewModel>();
...
Which triggers the exception:
Error activating IRecipeRepository No matching bindings are available, and the type is not self-bindable.
Activation path:
2) Injection of dependency IRecipeRepository into parameter recipeRepository of constructor of type HomeViewModel
1) Request for HomeViewModel
But if I attempt to get an instance of HomeViewModel directly after calling kernel.Bind in RegisterServices then it works fine.
Here's what the HomeViewModel looks like (some details removed for sake of brevity):
public class HomeViewModel
{
public HomeViewModel(IRecipeRepository recipeRepository,
IUserAccountRepository userAccountRepository)
{
this.recipeRepository = recipeRepository;
this.userAccountRepository = userAccountRepository;
}
//
// Some details removed for sake of brevity
//
private readonly IRecipeRepository recipeRepository;
private readonly IUserAccountRepository userAccountRepository;
}
Any idea what I'm missing? Why is the controller "special" in this case?
Related
I´m developing an ASP.NET MVC Application, in which I use NHibernate and Ninject.
The Problem is caused by the following Controller:
public class ShoppingCartController : Controller
{
private readonly Data.Infrastructure.IShoppingCartRepository _shoppingCartRepository;
private readonly Data.Infrastructure.IShopItemRepository _shopItemRepository;
public ShoppingCartController(Data.Infrastructure.IShoppingCartRepository shoppingCartController,
Data.Infrastructure.IShopItemRepository shopItemRepository)
{
_shoppingCartRepository = shoppingCartController;
_shopItemRepository = shopItemRepository;
}
public ActionResult AddToShoppingCart(FormCollection formCollection)
{
var cartItem = new Data.Models.ShoppingCartItem();
cartItem.ChangeDate = DateTime.Now;
cartItem.ShopItem = _shopItemRepository.GetShopItem(SessionData.Data.Info, Convert.ToInt32(formCollection["shopItemId"]));
//IF I DONT´T CALL THE METHOD ABOVE, AddToCart works
_shoppingCartRepository.AddToCart(SessionData.Data.Info, cartItem);
//BUT IF I CALL THE GetShopItem METHOD I GET THE EXCEPTION HERE!
return RedirectToAction("Index", "Shop");
}
}
I know most of the Time this Exception is caused by wrong Mapping, but I´m pretty sure that my Mapping is right because the AddToCart-Method works if I don´t call GetShopItem...
So here is the Code of the ShopItemRepository:
public class ShopItemRepository : ReadOnlyRepository<ShopItem>, IShopItemRepository
{
public ShopItemRepository(IUnitOfWork uow) : base(uow)
{
}
public ShopItem GetShopItem(SessionParams param, int id)
{
return CurrentSession.QueryOver<ShopItem>()
.Where(x => x.ProcessId == param.ProcessId &&
x.CatalogueId == param.CatalogueId &&
x.Id == id)
.SingleOrDefault();
}
public IList<ShopItem> GetShopItems(SessionParams param)
{
return CurrentSession.GetNamedQuery("GetShopItems")
.SetParameter("requestor_id", param.RequestorId)
.SetParameter("recipient_id", param.RecipientId)
.SetParameter("process_id", param.ProcessId)
.SetParameter("catalogue_id", param.CatalogueId)
.List<ShopItem>();
}
}
And finally the Code of my UnitOfWork (basically it is just a Wrapper for the Session because I don´t want to reference NHibernate in my MVC Project)
public class UnitOfWork : IUnitOfWork, IDisposable
{
private NHibernate.ISession _currentSession;
public NHibernate.ISession CurrentSession
{
get
{
if(_currentSession == null)
{
_currentSession = SessionFactoryWrapper.SessionFactory.OpenSession();
}
return _currentSession;
}
}
public void Dispose()
{
if(_currentSession != null)
{
_currentSession.Close();
_currentSession.Dispose();
_currentSession = null;
}
GC.SuppressFinalize(this);
}
}
Addendum:
My NinjectWebCommon Class
public static class NinjectWebCommon
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
/// <summary>
/// Starts the application
/// </summary>
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
bootstrapper.Initialize(CreateKernel);
}
/// <summary>
/// Stops the application.
/// </summary>
public static void Stop()
{
bootstrapper.ShutDown();
}
/// <summary>
/// Creates the kernel that will manage your application.
/// </summary>
/// <returns>The created kernel.</returns>
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
return kernel;
}
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IUnitOfWork>().To<UnitOfWork>().InRequestScope();
kernel.Bind<Data.Infrastructure.ICatalogueRepository>().To<Data.Repositories.CatalogueRepository>();
kernel.Bind<Data.Infrastructure.ICategoryRepository>().To<Data.Repositories.CategoryRepository>();
kernel.Bind<Data.Infrastructure.IContactRepository>().To<Data.Repositories.ContactRepository>();
kernel.Bind<Data.Infrastructure.IProcessRepository>().To<Data.Repositories.ProcessRepository>();
kernel.Bind<Data.Infrastructure.IShopItemRepository>().To<Data.Repositories.ShopItemRepository>();
kernel.Bind<Data.Infrastructure.IShoppingCartRepository>().To<Data.Repositories.ShoppingCartRepository>();
}
}
IUnitOfWork is set to RequestScope so in the Case of ShoppingCartController, the two Repositories share the same UOW right?
Maybe this could cause the Problem?
Are you sure that this isn´t caused by wrong mapping? I had the same Issue and could resolve it by checking my mappings again!
I am running into the below error the first time my ViewModel is being instantiated by the SimpleIoC. I believe I have setup the container as it should be, but for some reason, I am still getting the below error. Any ideas or assistance would be very much appreciated.
Microsoft.Practices.ServiceLocation.ActivationException was unhandled by user code
HResult=-2146233088
Message=Type not found in cache: Windows.UI.Xaml.Controls.Frame.
Source=GalaSoft.MvvmLight.Extras
StackTrace:
at GalaSoft.MvvmLight.Ioc.SimpleIoc.DoGetService(Type serviceType, String key) in c:\Users\Public\Downloads\CodePlex\MVVMLight\GalaSoft.MvvmLight\GalaSoft.MvvmLight.Extras (NET35)\Ioc\SimpleIoc.cs:line 532
at GalaSoft.MvvmLight.Ioc.SimpleIoc.GetService(Type serviceType) in c:\Users\Public\Downloads\CodePlex\MVVMLight\GalaSoft.MvvmLight\GalaSoft.MvvmLight.Extras (NET35)\Ioc\SimpleIoc.cs:line 768
at GalaSoft.MvvmLight.Ioc.SimpleIoc.MakeInstance[TClass]() in c:\Users\Public\Downloads\CodePlex\MVVMLight\GalaSoft.MvvmLight\GalaSoft.MvvmLight.Extras (NET35)\Ioc\SimpleIoc.cs:line 708
InnerException:
Here are pieces of my code related to this:
ViewModelLocator.cs (Located in my Win8 project)
public class ViewModelLocator
{
/// <summary>
/// Initializes a new instance of the ViewModelLocator class.
/// </summary>
public ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
if (ViewModelBase.IsInDesignModeStatic)
{
// Create design time view services and models
//SimpleIoc.Default.Register<IDataService, DesignDataService>();
}
else
{
// Create run time view services and models
//SimpleIoc.Default.Register<IDataService, DataService>();
SimpleIoc.Default.Register<INavigationService, NavigationService>();
SimpleIoc.Default.Register<IParseService, ParseService>();
SimpleIoc.Default.Register<IServiceHandler, ServiceHandler>();
}
SimpleIoc.Default.Register<MainViewModel>();
SimpleIoc.Default.Register<ActionViewModel>();
}
public MainViewModel MainVM
{
get
{
return ServiceLocator.Current.GetInstance<MainViewModel>();
}
}
public ActionViewModel ActionVM
{
get
{
return ServiceLocator.Current.GetInstance<ActionViewModel>();
}
}
public static void Cleanup()
{
// TODO Clear the ViewModels
}
}
MainViewModel.cs Constructor
public class MainViewModel : ViewModelBase
{
#region Variables
private readonly INavigationService _navigationService;
private readonly IParseService _parseService;
#endregion
/// <summary>
/// Initializes a new instance of the MainViewModel class.
/// </summary>
public MainViewModel(INavigationService navigationService, IParseService parseService)
{
if (IsInDesignMode)
{
// Code runs in Blend --> create design time data.
}
else
{
_navigationService = navigationService;
_parseService = parseService;
BuildCommonData();
}
}
I know this is long overdue, but here is the offending code in the implementation of my NavigationService class.
NavigationService class (Before)
public class NavigationService : INavigationService
{
/// <summary>
/// Gets the root frame.
/// </summary>
private Frame RootFrame;
public NavigationService(Frame rootFrame)
{
RootFrame = rootFrame;
}
public event NavigatingCancelEventHandler Navigating;
public void Navigate<T>(object parameter = null)
{
var type = typeof(T);
RootFrame.Navigate(type, parameter);
}
public void Navigate(string type, object parameter = null)
{
RootFrame.Navigate(Type.GetType(type), parameter);
}
public void GoBack()
{
if (RootFrame.CanGoBack)
{
RootFrame.GoBack();
}
}
public void GoForward()
{
if (RootFrame.CanGoForward)
{
RootFrame.GoForward();
}
}
}
I simply took out the constructor, and made the RootFrame private variable a property. Like so:
public class NavigationService : INavigationService
{
/// <summary>
/// Gets the root frame.
/// </summary>
private static Frame RootFrame
{
get { return Window.Current.Content as Frame; }
}
public event NavigatingCancelEventHandler Navigating;
public void Navigate<T>(object parameter = null)
{
var type = typeof(T);
RootFrame.Navigate(type, parameter);
}
public void Navigate(string type, object parameter = null)
{
RootFrame.Navigate(Type.GetType(type), parameter);
}
public void GoBack()
{
if (RootFrame.CanGoBack)
{
RootFrame.GoBack();
}
}
public void GoForward()
{
if (RootFrame.CanGoForward)
{
RootFrame.GoForward();
}
}
}
Simple, I know, but hope it's of some use.
I was getting the same error today in my Xamarin project. The actual error given was "System.Reflection.TargetInvocationException: 'Exception has been thrown by the target of an invocation.'" and then when I look up the InnerException I could see the actual error, which is Type not found in cache.
It was a silly mistake that I was using DataService instead of IDataService for the Constructor Dependency Injection.
public SearchViewModel(DataService dataService, IErrorLoggingService errorLoggingService, IDialogService dialogService, IResourceService resourceService, INavigationService navigationService) {
SearchCommand = new AsyncRelayCommand <SearchFilter>(SearchAsync);
DataService = dataService;
ErrorLoggingService = errorLoggingService;
DialogService = dialogService;
ResourceService = resourceService;
NavigationService = navigationService;
CancelCommand = new RelayCommand(Cancel);
}
And just for your information, this is how I registered my service.
SimpleIoc.Default.Register<IDataService, DataService>();
So the issue was fixed after changing to IDataService. Hope it helps.
I am trying to use the InSingletonScope for one of my service interface. However it is still creating a new instance of the object per web request. basically it behaves like an InRequestScope in my asp.net mvc 4 application.
I thought InSingletonScope is for the life time of the IIS process?
I register the following implementation for the interface in one of my NinjectModule. if I resolve it right away, repo1 and repo2 are actually the same instance. However, in my controller every request result in a new instance.
-------------------- Module registration
public class RepositoryModule : NinjectModule
{
#region Overrides of NinjectModule
public override void Load()
{
Bind<IFakeRepository>().To<FakeRepository>().InSingletonScope();
// following code onle execute the constructor once
var repo1String = Kernel.Get<IFakeRepository>().GetString();
var repo2String = Kernel.Get<IFakeRepository>().GetString();
}
#endregion
}
-------------------- Repository interface and implementation
public interface IFakeRepository
{
string GetString();
}
public class FakeRepository : IFakeRepository
{
public FakeRepository()
{
// every web request execute this constructor
Debug.Write("FakeRepository constructor called");
}
#region Implementation of IFackRepository
public string GetString()
{
return "dummy string";
}
#endregion
}
------------------ web api controller
public class TestRepoController : ApiController
{
public IFakeRepository FakeRepository { get; set; }
public TestRepoController(IFakeRepository fakeRepository)
{
FakeRepository = fakeRepository;
}
public string Get()
{
return FakeRepository.GetString();
}
}
----------------- web api route registration
config.Routes.MapHttpRoute(
name: "TestTakeRoutePost",
routeTemplate: "Fake",
defaults: new { controller = "TestRepo" }
);
----------------- NinjectWebCommon
[assembly: WebActivator.PreApplicationStartMethod(typeof(PNI.MediaServer.Application.App_Start.NinjectWebCommon), "Start")]
[assembly: WebActivator.ApplicationShutdownMethodAttribute(typeof(PNI.MediaServer.Application.App_Start.NinjectWebCommon), "Stop")]
public static class NinjectWebCommon
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
/// <summary>
/// Starts the application
/// </summary>
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
bootstrapper.Initialize(CreateKernel);
}
/// <summary>
/// Stops the application.
/// </summary>
public static void Stop()
{
bootstrapper.ShutDown();
}
/// <summary>
/// Creates the kernel that will manage your application.
/// </summary>
/// <returns>The created kernel.</returns>
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
//load all Binds defined in the classes that inherit NinhectModule
kernel.Load(Assembly.GetExecutingAssembly());
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
// Set Web API Resolver
GlobalConfiguration.Configuration.DependencyResolver = new PniNinjectDependencyResolver(kernel);
return kernel;
}
}
I'm subclassing the AuthorizeAttribute so I can implement token authentication whereby the token is passed in the request header. I'm also using Ninject for IoC. The overriden OnAuthorization method gets called and validates the token but I still receive a 401.
Any ideas on why this is happening?
TokenAuthorisationAttribute.cs
public class TokenAuthorisationAttribute : AuthorizeAttribute
{
private readonly IRepository _repository;
public TokenAuthorisationAttribute(IRepository repository)
{
_repository = repository;
}
public override void OnAuthorization(
HttpActionContext actionContext)
{
if (!ValidateToken(actionContext.ControllerContext.Request))
HandleUnauthorizedRequest(actionContext);
base.OnAuthorization(actionContext);
}
private bool ValidateToken(HttpRequestMessage request)
{
const string authenticationToken = "Authentication-Token";
var token = request.Headers.GetValues(authenticationToken).FirstOrDefault();
if (token == null)
return false;
var device = _repository.FindSingleOrDefault<Device>(x => x.Id.Equals(token));
if (device == null || !token.Equals(device.Id))
return false;
return true;
}
}
NinjectWebCommon.cs
public static class NinjectWebCommon
{
private static readonly Bootstrapper Bootstrapper = new Bootstrapper();
/// <summary>
/// Starts the application
/// </summary>
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
Bootstrapper.Initialize(CreateKernel);
}
/// <summary>
/// Stops the application.
/// </summary>
public static void Stop()
{
Bootstrapper.ShutDown();
}
/// <summary>
/// Creates the kernel that will manage your application.
/// </summary>
/// <returns>The created kernel.</returns>
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);
return kernel;
}
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
var connectionString = ConfigurationManager.ConnectionStrings["MONGOHQ_URL"].ConnectionString;
var databaseName = ConfigurationManager.AppSettings["Database"];
kernel.Bind<IRepository>().To<MongoRepository>()
.WithConstructorArgument("connectionString", connectionString)
.WithConstructorArgument("databaseName", databaseName);
kernel.BindHttpFilter<TokenAuthorisationAttribute>(FilterScope.Global);
}
I managed to resolve this issue by overriding the IsAuthorized method instead of OnAuthorization. Not 100% sure if this is the right approach? Any opinions ??
public class TokenAuthorisationAttribute : AuthorizeAttribute
{
private readonly IRepository _repository;
public TokenAuthorisationAttribute(IRepository repository)
{
_repository = repository;
}
protected override bool IsAuthorized(HttpActionContext actionContext)
{
if (actionContext.Request.Headers.Authorization == null)
return false;
var authToken = actionContext.Request.Headers.Authorization.Parameter;
var decodedToken = Encoding.UTF8.GetString(Convert.FromBase64String(authToken));
var deviceToken = new DeviceToken(decodedToken);
var device = _repository.FindSingleOrDefault<Device>(x => x.Id.Equals(deviceToken.GetDeviceId()));
if (device != null)
{
HttpContext.Current.User = new GenericPrincipal(new ApiIdentity(device), new string[] {});
return true;
}
return base.IsAuthorized(actionContext);
}
}
The ASP.NET WebAPI is an open source project. So you can read the correspondingly codes here:
AuthorizationFilterAttribute http://aspnetwebstack.codeplex.com/SourceControl/changeset/view/03357424caf5#src%2fSystem.Web.Http%2fFilters%2fAuthorizationFilterAttribute.cs
AuthorizeAttribute
http://aspnetwebstack.codeplex.com/SourceControl/changeset/view/03357424caf5#src%2fSystem.Web.Http%2fAuthorizeAttribute.cs
There are two facts an AuthorizationFilterAttribute takes in to consider when it is making decision:
Is OnAuthorization throw exception; or
Is the actionContext's Response field is filled;
Either one is fulfilled, the remaining action filters and action are shortcut.
Based on your code, I'm curious if the function HandleUnauthorizedRequest does either of the operation above.
The reason why overriding IsAuthorized works, is because it works at AuthorizeAttribute level. The OnAuthorization call to the IsAuthorized overload and set value to actionContext's Request property.
Thanks,
Troy
I have created an multi thread application on IIS (ASP.NET MVC), When the threading server started it creates 10 thread and it's execting workitems into the threads.
Usually my application working well, but some time i have got errors and i'm sure that problem is coming from fluent configuration. And I'm sure again i have made some mistake :)
Here is the my SessionFactory Class :
public class NHibernateHelper
{
private static ISessionFactory sessionFactory;
/// <summary>
/// SessionFactory is static because it is expensive to create and is therefore at application scope.
/// The property exists to provide 'instantiate on first use' behaviour.
/// </summary>
private static ISessionFactory SessionFactory
{
get
{
if (sessionFactory == null)
{
sessionFactory = CreateSessionFactory();
}
return sessionFactory;
}
}
/// <summary>
/// CreateSessionFactory
/// </summary>
/// <returns></returns>
private static ISessionFactory CreateSessionFactory()
{
IPersistenceConfigurer dbConfigurer = MsSqlConfiguration.MsSql2005
.ConnectionString("connection string ..")
.Cache(c => c
.UseQueryCache()
.ProviderClass<NoCacheProvider>()
).ShowSql()
.CurrentSessionContext<ThreadStaticSessionContext>();
return Fluently
.Configure()
.Database(dbConfigurer)
.Mappings(mc =>
{
mc.FluentMappings.Add(typeof(UserMap));
mc.FluentMappings.Add(typeof(ApplicationMap));
mc.FluentMappings.Add(typeof(SubscriptionsMap));
})
.BuildSessionFactory();
}
public static ISession GetCurrentSession()
{
if (!CurrentSessionContext.HasBind(SessionFactory))
{
CurrentSessionContext.Bind(SessionFactory.OpenSession());
}
return SessionFactory.GetCurrentSession();
}
public static void DisposeSession()
{
var session = GetCurrentSession();
session.Close();
session.Dispose();
}
public static void BeginTransaction()
{
GetCurrentSession().BeginTransaction();
}
public static void CommitTransaction()
{
var session = GetCurrentSession();
if (session.Transaction.IsActive)
session.Transaction.Commit();
}
public static void RollbackTransaction()
{
var session = GetCurrentSession();
if (session.Transaction.IsActive)
session.Transaction.Rollback();
}
}
Every thread is calling NHibernateHelper class with this line inside of itself ;
var myobjectinstance = new ObjectInstance();
NHibernateHelper.GetCurrentSession().Save( myobjectinstance );
I saw that, when i started server some time it has invoking 300.000 work item for test purpose successfully. But sometime it's giving errors about 2-3 workitem.
The exception is :
[0] = {"An invalid or incomplete configuration was used while creating a SessionFactory. Check PotentialReasons collection, and InnerException for more detail.\r\n\r\n"}
Inner excetion is :
Object reference not set to an instance of an object.
Inner exception stack trace is :
at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
at System.Collections.Generic.Dictionary`2.set_Item(TKey key, TValue value)
at NHibernate.Impl.SessionFactoryObjectFactory.AddInstance(String uid, String name, ISessionFactory instance, IDictionary`2 properties)
at NHibernate.Impl.SessionFactoryImpl..ctor(Configuration cfg, IMapping mapping, Settings settings, EventListeners listeners)
at NHibernate.Cfg.Configuration.BuildSessionFactory()
at FluentNHibernate.Cfg.FluentConfiguration.BuildSessionFactory()
in d:\Builds\FluentNH\src\FluentNHibernate\Cfg\FluentConfiguration.cs:line 93
Any suggestion or help are welcome
It looks like the CreateSessionFactory method is called multiple times. The sessionFactory static field access is not synchronized in this method which makes it not thread safe:
private static ISessionFactory SessionFactory
{
get
{
if (sessionFactory == null)
{
sessionFactory = CreateSessionFactory();
}
return sessionFactory;
}
}
Make sure to always synchronize access to shared resources in multithreaded applications. There's a common used pattern in this situation called singleton.