How to register FluentNHibernate with Ninject? - fluent-nhibernate

I'm setting up an ASP.NET MVC4 application and I'm using Ninject as my DI container.
In a previous project I used StructureMap with the following setup in my registry:
For<IAutoPersistenceConfiguration>()
.Use<Sql2008AutoPersistenceConfiguration>()
.Ctor<string>("connectionString")
.Is("SomeConnectionStringHere");
For<ISessionSource>()
.Singleton()
.Use(x => new SessionSource(x.GetInstance<IAutoPersistenceConfiguration>().Build()));
Now I try to a similar setup in Ninject. My try so far is:
Bind<IAutoPersistenceConfiguration>()
.To<Sql2008AutoPersistenceConfiguration>()
.WithConstructorArgument("connectionString", "SomeConnectionStringHere");
Bind<ISessionSource>()
.ToMethod(x => new SessionSource(
x.Kernel.Get<IAutoPersistenceConfiguration>().Build())).InSingletonScope();
When I run this I get an FluentConfigurationException:
An invalid or incomplete configuration was used while creating a SessionFactory.
The other classes are all the same; IAutoPersistenceConfiguration and Sql2008AutoPersistenceConfiguration are all the same as before. The version of NHibernate and FluentNHibernate are the same as before as well.
What am I doing incorrectly?

Turns out my Ninject setup was correct. The exception I got hid an inner exception that I did not look at initially (see my own comment to my question). Once I saw the inner exception all I had to do was fix my connection string and everything worked.

Related

Lost scope using DependencyResolver in another class library, using Castle Windsor and FluentNhibernate and NHibernate

In my WCF project I register my interface using Castle Windsor in the global.asax:
Component.For<IStrategy>()
.ImplementedBy<MyStrategy>()
.LifestylePerWcfOperation(),
Then later on in the same file I configure NHibernate using FluentNhibernate using a provider:
FluentConfiguration configuration = Fluently.Configure()
.Database(
MsSqlConfiguration.MsSql2008.ConnectionString(myConnString)
.Provider<ConnectionProvider>())
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<TenantMap>()) etc etc
However this ConnectionProvider is hosted in a common shared dll library as there are other WCF services that need to use it. I want to register this dependency as below but it doesn't work which means I have to manually new up a instance.
public ConnectionProvider()
{
// doesnt work
using (IDependencyScope scope = GlobalConfiguration.Configuration.DependencyResolver.BeginScope())
{
_myStrategy = scope.GetService<IStrategy>();
}
}
Is there anyway to make this work? Its like its lost scope as its in another assembly now. In the same assembly the DependencyScope works fine and creates an instance, but I want to keep it in a shared dll.
EDIT: The error I get is "System.Web.Http.Dependencies.EmptyResolver" on a watch on this bit of code: GlobalConfiguration.Configuration.DependencyResolver
I can see several problems with the code above:
1) You are registering IStrategy,MyStrategy with a per WcfOperation lifestyle. This means that windsor will create a strategy for each WcfOperation. On the otherhand you are trying to manually set the lifestyle of the component by using scope.GetService. For scope.GetService to work you will need a lifestyle scoped.
2) Assuming that the code for ConnectionProvider above is the constructor, it seems that the constructor is trying to get something from the container. This is in general a bad idea, and even worse when using an Ioc container like windsor. Instead pass the IStrategy to the constructor (inject it).
3) Seeing that you are calling the container a constructor here, probably means that you are not adhering to the principle that there should be only 3 calls to the container, 1 to register component, 1 to retrieve a top level component, and 1 to release the container.
I suggest you read a bit more about depedency injection and Ioc containers in general to fully understand how to work with this container.

RoleProvider injection with Ninject

First off I want to say there is a ton of answers on SO and google searches surrounding this, however I'm running into an issue that prevents those solutions from working. The answer here seems to be the way to go. (kernel.Inject(Roles.Provider);)
The issue that I'm having is that when I'm trying to inject the RoleProvider Roles.Provider is null, however my custom provider is found in the list within Roles.Providers. I am thinking that Ninject is trying to access the role provider too soon.
In my NinjectWebCommon class it appears that it's using WebActivator to start itself. [assembly: WebActivator.PreApplicationStartMethod(typeof(Admin.App_Start.NinjectWebCommon), "Start")]
It appears that all of the articles I've come across are using older versions of Ninject and are doing a lot of the heavy lifting in the Global.asax Application_Start... Using my implementation how can I get DI working for a custom role provider?
I'm using the [Inject] attribute within my custom provider.
The WebActivator pipeline runs way before even the standard ASP.NET stack is created. It means that you won't have access to anything created by ASP.NET during bootstrap in NinjectWebCommon.
Use that file only to declare bindings that do not depend on ASP.NET stuff to be up.
In order to get around this issue, you should use Global.asax Application_Start handler to load any additional modules/bindings that are dependend on ASP.NET stuff such as Roles.Provider.
Here is a suggestion that may solve your problem:
public void Application_Start()
{
var kernel = (new Bootstrapper()).Kernel;
kernel.Inject(Roles.Provider);
//Other initialization stuff
}
The Bootstrapper class is a lazy singleton that has a static IKernel initialized within your NinjectWebCommon.cs. So this is the proper way of retrieving the configured kernel instance from outside your NinjectWebCommon.
Give it a try.

Windsor Facility Error

Everytime I try to add a facility to my Windsor container instance, I see the following exception:
Derived method 'Dispose' in type 'Castle.Facilities.WcfIntegration.WcfFacility' from assembly 'Castle.Facilities.WcfIntegration, Version=2.5.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc' cannot reduce access.
This has happened for both the AutoTx facility, and the WCF facility.
Looking in reflector, the Dispose method in this class is protected, and is also protected in the class from which it inherits.
My project references the same versions of Castle.Windsor and Castle.Core that the WcfFacility demo references.
Any ideas?
I've scoured the web for answers, by no luck.
Thanks!
This was a versioning issue! My project was referencing an out of date Castle.Windsor.dll

Nhibernate Validator

In my unit tests I am getting an error when I am debugging. The weird thing is I do not get this whenever I just run the test (it's only when debugging a test). I get an exception whenever I try to validate one of my entities with NHibernate Validator. The following line throws the exception below.
InvalidValue[] invalidValues = validatorEngine.Validate(group);
Exception: The ProxyFactoryFactory was not configured.
Initialize 'proxyfactory.factory_class' property of the session-factory configuration section with one of the available NHibernate.ByteCode providers.
Example:
NHibernate.ByteCode.LinFu.ProxyFactoryFactory, NHibernate.ByteCode.LinFu
Example:
NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle
I'm configuring the validator engine like this:
var nhvConfiguration = new FluentConfiguration();
nhvConfiguration
.SetDefaultValidatorMode(ValidatorMode.OverrideAttributeWithExternal)
.Register(Assembly.Load("Business.Objects")
.ValidationDefinitions());
validatorEngine = new ValidatorEngine();
validatorEngine.Configure(nhvConfiguration);
I'm not sure what's going on here. Anyone know why I am getting this error while debugging and not while just running the test?
I'm using NHibernate 3.1 and NHibernate validator 1.3
I haven't used nhibernate validator before but nHibernate needs a ProxyFactory class to be specified as part of the configuration other wise it throws this sort of error
I generally use the xml mapping files and config files
this is the line that I would normally add
<property name="proxyfactory.factory_class">NHibernate.ByteCode.LinFu.ProxyFactoryFactory, NHibernate.ByteCode.LinFu</property>
Any of the proxy factories would do. it comes down to preference.
The reason it was throwing this exception was unrelated to any nhibernate configuration. The following post explains why I was getting this exception.
C# Uncaught exception in unit test

NHibernate.MappingException: Unknown entity class

I am trying to get test running that uses FluentNHibernate to map my
entities.
I get unknown entity class error.
I have a Domain project that has my entities and the mappings in a seperate
folder in that project.
My test project has the Nhibrenate configuration in the App.Config.
Any ideas please???
Malcolm
EDIT: I have this method that creats the ISessionFactory but I dont think this code is working and this is why it does not recoginze me mappings exist at all. The SessionFacoryCreator is the assembly with my AppConfig and Recipe is my assembly where the Domain objects are. Please HELLLLLLP!!!!
public static ISessionFactory Create()
{
Configuration cfg = new Configuration()
.AddAssembly(typeof(SessionFactoryCreator).Assembly)
.AddAssembly(typeof(Recipe).Assembly);
return cfg.BuildSessionFactory();
}
Have you read the wiki? Your example shows nothing of hooking Fluent NHibernate into the session factory building, that'd be why it isn't working. Start with the Getting Started guide.
How do you add your Entities to the Hibernate framework? Are you using AnnotationConfiguration or just Configuration? If you are using annotations you must add your annotated entity to the framwork. Otherwise, if you are using xml hibernate mapping, the syntax could be worng (iirc)
NHibernate and I keep on getting the following error: MappingException: Unkown Entity Class
If you get MappingException error, there are two things you should check out:
Make sure the name of the *.hbm.xml is spelled correctly — not *.hmb.xml nor *.mbh.xml
Make sure the Build Action property is set to “Embeded Resource.”