Does Fluent NHibernate provide an iSeries data provider? - fluent-nhibernate

I am trying to connect using Fluent NHibernate to our AS/400 iSeries DB2 server. I have the following code:
private static ISessionFactory CreateSessionFactory()
{
return Fluently.Configure()
.Database(DB2Configuration.Standard.ConnectionString("DataSource=MyServer;UserID=MyUser;Password=password;"))
.Mappings(m => m.FluentMappings.AddFromAssembly(Assembly.GetExecutingAssembly()))
.BuildSessionFactory();
}
I am running nhprof, and I get the error:
Could not load file or assembly 'IBM.Data.DB2' or one of its dependencies. The system cannot find the file specified.Could not load type IBM.Data.DB2.DB2Command, IBM.Data.DB2.
I know that IBM.Data.DB2.dll is the incorrect .dll for the iSeries. It should be loading IBM.Data.DB2.iSeries.dll, which is in my bin folder.
NHibernate has a way to load the iSeries dll. How can I tell Fluent to load it?

I figured it out, just in case anybody else is struggling with this.
I took out the nhibernate.cfg.xml file and did it in code. This code appears to work:
private static ISessionFactory CreateSessionFactory()
{
ISessionFactory factory = null;
var cfg = new Configuration();
cfg.DataBaseIntegration(x =>
{
x.ConnectionString = "DataSource=MyServer;UserID=MyUser;Password=password; DataCompression=True;";
x.Dialect<DB2400Dialect>();
x.Driver<DB2400Driver>();
});
factory = Fluently.Configure(cfg)
.Mappings(m => m.FluentMappings.AddFromAssembly(Assembly.GetExecutingAssembly()))
.BuildSessionFactory();
return factory;
}

Related

NHibernate Fluent Add external Assembly mappings

I have a project with my mappings and entities stored in other class libraries and NHibernate layers in another project. In my testing project I would like to add these mapping via fluently configure... Mappings... via assebly and not individually. In my code below you can see I added just one entity.. But I would like to configure it to scan my other assemblies. I am sure I am just missing the obvious here.. any pointers would be greatly appreciated...
[Test]
public void Can_generate_schemaFluently()
{
var cfg = new Configuration();
cfg.Configure();
Configuration configuration = null;
ISessionFactory SessionFactory = null;
ISession session = null;
SessionFactory = Fluently.Configure(cfg)
*** WOULD LIKE TO ADD MY ASSEBLIES and autoscan for objects instead ***
.Mappings(m => m.FluentMappings
.Add(typeof(StudentEOMap))
)
.ExposeConfiguration(x => configuration = x)
.BuildSessionFactory();
session = SessionFactory.OpenSession();
object id;
using (var tx = session.BeginTransaction())
{
var result = session.Get<StudentEO>(1541057);
tx.Commit();
Assert.AreEqual(result.StudId, 1541057);
}
session.Close();
}
AutoMapping
If you want to filter through types, you can use the IAutomappingConfiguration and derive from DefaultAutomappingConfiguration like this:
public class StandardConfiguration : DefaultAutomappingConfiguration
{
public override bool ShouldMap(Type type)
{
// Entity is the base type of all entities
return typeof(Entity).IsAssignableFrom(type);
}
}
You can also use DefaultAutomappingConfiguration if you have no need to filter. But my further example uses the StandardConfiguration.
Change your configuration like this, to populate your types to FluentNHibernate:
SessionFactory = Fluently.Configure(cfg)
.Mappings(m => MapMyTypes(m))
.ExposeConfiguration(x => configuration = x)
.BuildSessionFactory();
And the MapMyTypes method should look like this:
private void MapMyTypes(MappingConfiguration m)
{
m.AutoMappings.Add(AutoMap.Assemblies(new StandardConfiguration(),
Assembly.GetAssembly(typeof(Entity)),
Assembly.GetAssembly(typeof(OtherAssemblyEntity)))
);
}
You can add multiple Assemblies and all get filtered through the StandardConfiguration.
Edit
FluentMappings
It seems that i misread your question. To add mappings you can use a similar method to achieve that but without a IAutomappingConfiguration.
Just change the MapMyTypes method to:
private void MapMyTypes(MappingConfiguration m)
{
m.FluentMappings.AddFromAssembly(Assembly.GetAssembly(typeof(EntityMap)));
}
Combine
You can also combine the FluentMapping and the AutoMapping like this:
private Action<MappingConfiguration> MapMyTypes()
{
return m =>
{
MapFluent(m);
MapAuto(m);
};
}

NHibernate Validator with Fluent

I'm trying to get my schema export to work with Validators Expressed in my Domain Object. I have a [NotNull] attribute AND a ValidatioDef on a property but the column is still expressed as nullable by the schema export. Im sure its a config issue, but not sure where. Some wiring has gone haywire. Here is my config and gerneration code.
[Test]
public void GenerateSchemaWithValidation()
{
var nhvConfiguration = new FluentConfiguration();
nhvConfiguration
.SetDefaultValidatorMode(ValidatorMode.UseExternal)
.Register(Assembly.Load("MyDomainAssembly")
.ValidationDefinitions())
.IntegrateWithNHibernate
.ApplyingDDLConstraints()
.And
.RegisteringListeners();
var nhibernateConfig = new Configuration().Configure();
var validatorEngine = new ValidatorEngine();
validatorEngine.Configure(nhvConfiguration);
nhibernateConfig.Initialize(validatorEngine);
ConfigureDatabaseAndMappings()
.ExposeConfiguration(cfg => new SchemaExport(cfg).Create(true, true))
.BuildSessionFactory();
}
protected static FluentConfiguration ConfigureDatabaseAndMappings()
{
return Fluently.Configure()
.Database(
MsSqlConfiguration.MsSql2005.ConnectionString(c => c.FromConnectionStringWithKey("MyDb"))
.ShowSql())
.Mappings(m =>
m.FluentMappings.AddFromAssemblyOf<MediaDescriptionMap>()
.Conventions.AddFromAssemblyOf<WellNamedForeignKeyColumnConvention>());
}
Yes you can. You have to tell Fluent to tell NHibernate via ExposeConfiguration:
This works.
[Test]
public void DoGenerateSchema()
{
ConfigureDatabaseAndMappings()
.ExposeConfiguration(ExportSchema)
.BuildSessionFactory();
}
private static void ExportSchema(Configuration cfg)
{
var nhvConfiguration = new FluentConfiguration();
nhvConfiguration
.SetDefaultValidatorMode(ValidatorMode.UseAttribute)
.Register(Assembly.Load("MyDomainAssembly")
.ValidationDefinitions())
.IntegrateWithNHibernate
.ApplyingDDLConstraints()
.And
.RegisteringListeners();
var validatorEngine = new ValidatorEngine();
validatorEngine.Configure(nhvConfiguration);
cfg.Initialize(validatorEngine);
new SchemaExport(cfg).Create(true, true);
}
and for those wondering like I was I know see that ValidatorMode.UseAttribute only picks up e.g.[NotNull] and ValidatorMode.UseExternal picks up ValidationDefs
All this so that business rules are encapsulated in the domain/business tier not by the database mappings. (check HunabKu's blog for some good discussions and examples)
NHibernate Validator doesn't alter the mappings that are created, it just validates your entity against your rules before saving. You need to also specify in your mappings that you don't want your columns to be nullable.
Map(x => x.Property)
.Not.Nullable();
If you're doing that for a lot of properties, it might be worth looking into using a convention; specifically a PropertyAttributeConvention would work well in your case.

Id property not populated

I have an identity mapping like so:
Id(x => x.GuidId).Column("GuidId")
.GeneratedBy.GuidComb().UnsavedValue(Guid.Empty);
When I retrieve an object from the database, the GuidId property of my object is Guid.Empty, not the actual Guid (the property in the class is of type System.Guid). However, all of the other properties in the object are populated just fine.
The database field's data type (SQL Server 2005) is uniqueidentifier, and marked as RowGuid.
The application that is connecting to the database is a VB.NET Web Site project (not a "Web Application" or "MVC Web Application" - just a regular "Web Site" project). I open the NHibernate session through a custom HttpModule. Here is the HttpModule:
public class NHibernateModule : System.Web.IHttpModule
{
public static ISessionFactory SessionFactory;
public static ISession Session;
private static FluentConfiguration Configuration;
static NHibernateModule() {
if (Configuration == null) {
string connectionString = cfg.ConfigurationManager.ConnectionStrings["myDatabase"].ConnectionString;
Configuration = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2005.ConnectionString(cs => cs.Is(connectionString)))
.ExposeConfiguration(c => c.Properties.Add("current_session_context_class", "web"))
.Mappings(x => x.FluentMappings.AddFromAssemblyOf<LeadMap>().ExportTo("C:\\Mappings"));
}
SessionFactory = Configuration.BuildSessionFactory();
}
public void Init(HttpApplication context) {
context.BeginRequest += delegate {
Session = SessionFactory.OpenSession();
CurrentSessionContext.Bind(Session);
};
context.EndRequest += delegate {
CurrentSessionContext.Unbind(SessionFactory);
};
}
public void Dispose() {
Session.Dispose();
}
}
The strangest part of all, is that from my unit test project, the GuidId property is returned as I would expect. I even rigged it to go for the exact row in the exact database as the web site was hitting. The only differences I can think of between the two projects are
The unit test project is in C#
Something with the way the session is managed between the HttpModule and my unit tests
The configuration for the unit tests is as follows:
Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2005.ConnectionString(cs => cs.Is(connectionString)))
.Mappings(x => x.FluentMappings.AddFromAssemblyOf<LeadDetailMap>());
I am fresh out of ideas. Any help would be greatly appreciated.
Thanks
I had a similar problem when in the mapping attribute Name was not set. You can try to save your fluent mappings into Xmls and check them.

Fluent Nhibernate and quartz

I'm building a asp.net mvc web application. And I'm running quartz in the asp.net context.
I'm using fluent nhibernate for my or mappings.
I'm building a simple job that goes writes an entry in the database.
public void Execute(JobExecutionContext context)
{
ISession session = DataSourceConfiguration.GetSessionFactory().OpenSession();
session.SaveOrUpdate(new JobLogEntry() { Created = DateTime.Now, Message = "Twitter feed read" });
session.Close();
session.Dispose();
}
public static ISessionFactory GetSessionFactory()
{
return Fluently.Configure()
.Database(CurrentDataBaseConfiguration)
.Mappings(m =>
m.AutoMappings.Add(
AutoMap.AssemblyOf<Entry>()
.Where(t => t.Namespace == "QuickBlog.BlogModel.Entities")
))
.BuildSessionFactory();
}
Here is where the error occurs:
public static IPersistenceConfigurer CurrentDataBaseConfiguration
{
get
{
if (_dataBaseConfiguration != null)
return _dataBaseConfiguration;
var config = MsSqlConfiguration.MsSql2005
.ConnectionString(c => c.FromConnectionStringWithKey("QuickBlogDB"))
.UseReflectionOptimizer()
.Cache(c => c.Not
.UseQueryCache())
.ShowSql();
_dataBaseConfiguration = config;
return _dataBaseConfiguration;
}
}
The problem is that c.FromConnectionStringWithKey("QuickBlogDB") is null or empty. How do I get a hold of the configuration info in the quartz.net job?
First of all, you probably should not create your session factory inside your job. I would recommend of having a static class to hold session factory and initialize it in earlier stage, say applications Application_Start method.
It's more resource efficient (a lot) and makes it easier to debug problems as your app won't even start before configuration and preconditions are right.

NHibernate questions - modifying this example for Fluent NHibernate

I'm new to NHibernate...
I have been following this NHibernate Tutorial from Gabriel Schenker :
http://nhforge.org/wikis/howtonh/your-first-nhibernate-based-application.aspx
However, this tutorial uses hbm files. I would like to know - what do I need to do to modify the hepler class below (which creates a session factory) so that it uses my ClassMap files instead of hbm?
Also, is this the best way to deal with factory creation? How often will the factory be created in this example - once per request? (I'm not really sure I understand the lifetime of _sessionFactory in this case).
Thank you!
public class NHibernateHelper
{
private static ISessionFactory _sessionFactory;
private static ISessionFactory SessionFactory
{
get
{
if(_sessionFactory == null)
{
var configuration = new Configuration();
configuration.Configure();
configuration.AddAssembly(typeof(Product).Assembly);
_sessionFactory = configuration.BuildSessionFactory();
}
return _sessionFactory;
}
}
public static ISession OpenSession()
{
return SessionFactory.OpenSession();
}
}
Session factory usually should only be created once (using the singleton pattern) for the lifetime of the app.
And here is sample code for creating the SessionFactory with Fluent Nhibernate:
var mssqlConfig = MsSqlConfiguration
.MsSql2008
.ConnectionString(c => c.Is(connectionstring))
.UseOuterJoin()
.ProxyFactoryFactory("NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle");
var sessionFactory = Fluently.Configure()
.Database(mssqlConfig)
.Mappings(m => m.FluentMappings.AddFromAssembly(typeof(Product).Assembly))
.BuildSessionFactory();
Not using Fluent Config (from the top of my head, syntax might not be exact):
var config = new NHibernate.Cfg.Configuration().Configure();
var model = new PersistenceModel();
model.Configure(config);
model.AddMappingsFromAssembly(typeof(Product).Assembly);
var sessionFactory = config.BuildSessionFactory();