automapping Entities in nhibernate - fluent-nhibernate

hii i am having a little problem in mapping all the entities in contained in the namespace "nhibernateTest.Domain" . it basically contains all the Map Classes like , StudentMap, DepartmentMap etc. .. now in case of normal nhibernate what we used to do is :
private ISessionFactory _sessionFactory;
private Configuration _configuration;
[TestFixtureSetUp]
public void TestFixtureSetUp()
{
_configuration = new Configuration().Configure().AddAssembly("nHibernateTest");
_sessionFactory = _configuration.BuildSessionFactory();
}
now what it used to do is . look for all the "*.hbm.xml" files in my namespace and automatically map them...
can someone tell me how to do the same for fluent nHibernate ? so that it looks for all map classes and automatically map them so that i dont have to create the session separately for diffrent Map classes ?

You would need to specify your mappings when configuring Fluent NHibernate in your application. This is typically done by
Fluently.Configure()
.Database(/* your database settings */)
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<StudentMap>())
.ExposeConfiguration(/* alter Configuration */) // optional
.BuildSessionFactory();
The code above is from this excellent link which talks about how to configure Fluent.

Related

FluentNHibernate Mixing Fluent and Auto Mappings

Is there a clean way to mix fluent mappings with automappings? Ideally, I'd like to say "if I don't have a ClassMap for a domain object, then automap it". Is there a recommended approach? I'd rather not use attributes on my business objects that are data access related (ex: [UseAutoMapping]).
Yes - check out IAutoMappingOverride
Basically, any mappings which override the Automapping behaviour need to implement this interface.
e.g.
public class MyClassMap : IAutoMappingOverride<MyClass>
{
public void Override(AutoMapping<MyClass> mapping)
{
mapping.IgnoreProperty(host => host.HostName);
mapping.Table("BobsHardware");
}
}

Private fields in FluentNHibernate

I've configured Fluent NHibernate to map the entities in my project. None of my entities expose public properties (except their Id), all of their data is stored in private fields.
By using:
public override bool ShouldMap(Member member)
{
return member.Name == "Id" || (member.IsPrivate && member.IsField);
}
it successfully finds my fields, but then expects my database columns to be called things like _emailAddress.
How can I make it map _emailAddress to a column called EmailAddress? My SessionFactory initialisation looks like:
Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008.ConnectionString(c => c.FromConnectionStringWithKey("AppConnection")))
.Mappings(m => m.AutoMappings.Add(AutoMap.AssemblyOf<User>(new NHibMappingConfiguration())
.Conventions.Add(DefaultAccess.CamelCaseField(CamelCasePrefix.Underscore))))
.CurrentSessionContext("web")
.ExposeConfiguration(BuildSchema)
.BuildSessionFactory();
using obviously a default access convention.
Thanks,
Matt
i think you have a couple of options here.
1. you could create your own Convention for naming columns (use the INamingConvention interface. see here).
2. you could create a MappingOverride class for individual classes and define the column name for each one:
mapping.Map(x => x.Name).Column("MyColumnName");

Should i care/have knowledge about nHibernate before choosing Fluent nHibernate?

I was going through Fluent nhibernate wiki and i know that Fluent nhibernate is built on top of nHibernate... Should i care/have knowledge about nHibernate before choosing Fluent nHibernate? Any suggestion...
You absolutely need to learn NHibernate. Fluent NHibernate is only a wrapper over NHibernate's mapping API, and mapping is only a small part of working with NHibernate.
Queries (Criteria/HQL/LINQ), sessions, locking, lazy/eager loading, etc, are concepts that you must know when working with NHibernate and have nothing to do with Fluent NHibernate.
I say yes. If you know NHibernate's XML based mapping format, it's much easier to track down errors via fluent NH's [FluentMappingsContainer].ExportTo([e.g. Environment.CurrentDirectory]).
Edit: ASP.NET MVC example w/ StructureMap
StructureMap:
private static void ConfigureSQLiteInMemoryTest(IInitializationExpression init)
{
init.For<ISessionFactory>()
.Singleton()
.Use( Fluently.Configure()
.Database( SQLiteConfiguration.Standard.InMemory().AdoNetBatchSize( 100 ).ShowSql )
.Mappings( m => m.FluentMappings.AddFromAssemblyOf<MyEntity>() )
.ExposeConfiguration( config =>
{
config.SetProperty( NHEnvironment.ProxyFactoryFactoryClass,
typeof( ProxyFactoryFactory ).AssemblyQualifiedName );
} )
.BuildSessionFactory() );
init.For<ISession>()
.LifecycleIs( GetLifecycle() )
.Use( context =>
{
var session = context.GetInstance<ISessionFactory>().OpenSession();
new TestData( session, _nhConfig ).Create();
return session;
} );
}
Tell MVC to use a StructureMap based controller factory:
Global.asax.cs:
protected void Application_Start()
{
[...]
var controllerFactory = new StructureMapControllerFactory( ObjectFactory.Container );
ControllerBuilder.Current.SetControllerFactory( controllerFactory );
[...]
}
public class StructureMapControllerFactory : DefaultControllerFactory
{
private readonly IContainer _container;
public StructureMapControllerFactory( IContainer container )
{
_container = container;
}
protected override IController GetControllerInstance( RequestContext requestContext, Type controllerType )
{
if (controllerType == null)
return null;
return (IController)_container.GetInstance( controllerType );
}
}
of course, fluent nhibernate is mainly there to make mapping simpler (and type safe)
YES!
You will get completely lost if you do not understand at least the basics of NHibernate. NHibernate is a complex tool and fluent NHibernate really only makes working with it more convenient - it does not hide the complexity.
Try the answer for this question for tutorials
Where can i find a Fluent NHibernate Tutorial?
It makes sense to have a grasp of NHibernate before you learn fluent nhibernate. As #Jaguar says it sits on top of nhibernate.
It might be worth looking at nhlambdaextensions.googlecode.com - although this is going to be included in the next version!
For Nhibernate tutorials check out dimecasts or tekpub - or nhibernate.info - see question
Learning NHibernate
NHibernate is database agnostic. :)

Fluent mapping - entities and classmaps in different assemblies

When using fluent configuration to specify fluent mappings like this:
.Mappings(m => m.FluentMappings.AddFromAssembly(typeof(UserMapping).Assembly))
At the moment I am getting a "NHibernate.MappingException : No persister for" error.
Is it a problem that my Entities and my ClassMaps are in different assemblies? Presumably AddFromAssembly is interested in the assembly that holds the class maps, not the entities? (that is what I have assumed)
Thanks!
UPDATE:
Sorry for not responding to answers very quickly - I had to travel unexpectedly after setting the bounty.
Anyway, thanks for the responses. I've taken a look through them and have updated my code to use AddFromAssemblyOf rather than AddFromAssembly, but still am getting the same error. Possibly I am doing something stupid. Here is the full code for the session factory code I am using:
public class NHibernateHelper
{
private static ISessionFactory _sessionFactory;
private static ISessionFactory SessionFactory
{
get
{
if (_sessionFactory == null)
{
var mysqlConfig = FluentNHibernate.Cfg.Db.MySQLConfiguration
.Standard
.ConnectionString("CONNECTION STRING OMITTED")
.UseOuterJoin()
.ProxyFactoryFactory("NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle");
_sessionFactory = FluentNHibernate.Cfg.Fluently.Configure()
.Database(mysqlConfig)
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<User>())
.BuildSessionFactory();
}
return _sessionFactory;
}
}
public static ISession OpenSession()
{
return SessionFactory.OpenSession();
}
}
I receive this exception when trying to run a test in nunit that makes use of a repository using this session mechanism:
NHibernate.MappingException : No persister for: xxxx.Model.Entities.User
Thanks
P.S.:
I've tried using both and in AddFromAssemblyOf();
Project with mapping definitions (DataAccess) has reference to project with entities (Model).
What version of Fluent NHibernate are you using? There have been problems with the release candidate and the 1.0 release versions. You may want to consider downloading the latest version from the SVN repository.
http://fluent-nhibernate.googlecode.com/svn/trunk/
Additionally, you may want to check the connection string to make sure that it is completely correct, and you want to make sure that "User" below points to a class.
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<User>())
Also, I should mention that when you use AddFromAssemblyOf, fluent will try to map EVERY class in that assembly. If you have any other classes in that namespace you will want to filter them. There are several different ways to accomplish this. The simplest way is to just place all of the POCOs you want to map in their own namespace and then do something like the following.
.Mappings(m => m.AutoMappings
.Add(AutoMap.AssemblyOf<MyNamespace.Entities.MyClass>()
.Where(type => type.Namespace == "MyNamespace.Entities")
The Where clause will filter items you don't want mapped.
Is it a problem that my Entities and my ClassMaps are in different assemblies?
No there is nothing wrong with that as long as you ClassMap project have refrerence to your Entities project
anyway try this :
m.FluentMappings.AddFromAssemblyOf<UserMapping>()
if this doesn't work post the entire error
Certainly having your entities in a different assembly should not cause a problem as Yassir alludes to above.
According to the Fluent NHibernate Wiki the AddFromAssemblyOf method infers or reflects on the Assembly that contains all of your entities and will map to them when you supply any entity name to it. From the documentation on the FNH wiki you would construct the method as follows:
m.FluentMappings
.AddFromAssemblyOf<YourEntity>();
Therefore in your example, if the entity you are mapping is named User then your code should be constructed as follows:
m.FluentMappings
.AddFromAssemblyOf<User>();
Hope this is of help.
has this been solved? if not could you inlcude your setup?
for example here is my example one
public static ISessionFactory GetSessionFactory()
{
//Old way, uses HBM files only
//return (new Configuration()).Configure().BuildSessionFactory(); //requies the XMl file.
//get database settings.
Configuration cfg = new Configuration();//.Configure();
ft = Fluently.Configure(cfg);
//DbConnection by fluent
ft.Database
(
MsSqlConfiguration
.MsSql2005
.ConnectionString(c => c
.Server(".\\SqlExpress")
.Database("NhibTest")
.TrustedConnection()
)
.ShowSql()
.UseReflectionOptimizer()
);
//set up the proxy engine
//cfg.Properties.Add("proxyfactory.factory_class", "NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle");
//get mapping files.
ft.Mappings(m =>
{
//set up the mapping locations
m.FluentMappings.AddFromAssemblyOf<PersonMap>();//.ExportTo("C:\\mappingfiles");
//m.Apply(cfg);
});
//return the SessionFactory
return ft.BuildSessionFactory();
}
the project structure is as follows
project.Data <- mapping files, and Dao's (also hibernate session manager, containing the above code)
project.Core <- POCO's
project.UI
also have look here incase you have a mixture of Fluent NHibernate and NHibernate configuration
Finally have a look at S#arp Architectures way, as i think it includes this mixture
NhibernateSession <- function : private static ISessionFactory CreateSessionFactoryFor
Hope this helps

How to set a configuration property when using fluent nhibernate?

In particular, I'd like to set current_session_context_class. I know how to do it in hibernate.cfg.xml, but is it possible at all with pure fluent configuration?
You can use the method ExposeConfiguration on a FluentConfiguration instance, to access the original NHibernate Configuration object.
Then, you'll have access to the Properties property, and you will be able to add the current_session_context_class one.
Here is a the pseudo-code:
Fluently.Configure()
.Database(SQLiteConfiguration.Standard.InMemory)
.ExposeConfiguration(c =>
{
c.Properties.Add("current_session_context_class",
typeof(YourType).FullName);
})
//.AddMapping, etc.
.BuildSessionFactory();