FLuentNhibernate + Automapping - fluent-nhibernate

Anyone that can helt me with FluentNhibernate and automapping?
Check PotentialReasons collection, and InnerException for more detail. ----> FluentNHibernate.Cfg.FluentConfigurationException : An invalid or incomplete configuration was used while creating a SessionFactory. Check PotentialReasons collection, and InnerException for more detail. ----> FluentNHibernate.Visitors.ValidationException : The entity 'NHibernateSessionManager' doesn't have an Id mapped. Use the Id method to map your identity property. For example: Id(x => x.Id).
i´m trying to automap from my classes and here is the code:
FluentConfiguration config = Fluently.Configure()
.Database(MySQLConfiguration.Standard
.ConnectionString(c => c
.Server("127.0.0.1")
.Database("db")
.Username("root")
.Password("pass")));
_sessionFactory = config.Mappings(
m => m.AutoMappings.Add(AutoMap.AssemblyOf<Product>())
.ExportTo(#"c:\hbm\"))
.BuildSessionFactory();

AutoMap.AssemblyOf<Product>() tries to map all classes from the assembly.
Set a filer like AutoMap.AssemblyOf<Product>(t => t.Namespace.StartsWith(typeof(Product).Namespace))

Related

mapping from multiple assemblies

I have an assembly for mapping in nhibernate. some of the mapping classes in the assembly has reference in another assembly. how to configure mapping with reference to second assembly. I dont want to map the whole of the second assembly
Configuration cfg = new Configuration();
cfg.SetInterceptor(new NHInterceptor());
cfg.Configure(sessionFactoryConfigPath);
FluentConfiguration fluentConfiguration = Fluently.Configure(cfg)
.Mappings(m =>
{
m.FluentMappings
.AddFromAssembly(Assembly.Load("someassembly"))
.Conventions.Add(DefaultLazy.Always(),
OptimisticLock.Is(x => x.All()),
DynamicUpdate.AlwaysTrue(),
DynamicInsert.AlwaysFalse(),
DefaultCascade.None()
)
.Conventions.AddFromAssemblyOf<"someDateconventionobject">()
;
});
You can simply add a single mapping class:
m.FluentMappings
.Add<MappingClassFromOtherAssembly>()
Or use the Add(Type type) overload and Type.GetType(string typeName) method if you don't have a reference to the other assembly.

autopmapping with UseOverridesFromAssemblyOf doesn't call overriding classes of base class

i'm using automapping with fluent nHibernate, very simply, like so:
Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008
.ConnectionString(c => c
.Server("(local)\\sql2008")
.Database("nHibernate_test")
.TrustedConnection()))
.Mappings(m => m.AutoMappings.Add(
AutoMap.AssemblyOf<Domain.Airport>(cfg)
.UseOverridesFromAssemblyOf<ReaderMappingOverride>()
))
my overriding classes are something like that:
public class ReaderMappingOverride : IAutoMappingOverride<Domain.Reader>
{
public void Override(AutoMapping<Domain.Reader> mapping)
{
//use the reader ID as identifier of the class, instead of the ID field defined in superclass Entity
mapping.IgnoreProperty(r => r.Id);
mapping.Id(r => r.ReaderNumber);
}
}
where Reader is an abstract base-class.
if I use a seperate overriding classes for each sub-class it works OK.
Is there any way to define the overriding for all subclasses of the abstract class?
thanks,
Jhonny
ok, just answered my own question-
my problem was that i was trying to map a heirarchy which started with the Reader class, into a single table. but auto-mapping automatically ignores all abstract classes. what i did was just add this to the configuration section:
.Mappings(m => m.AutoMappings.Add(
AutoMap.AssemblyOf<Domain.Airport>(cfg)
.IncludeBase<Domain.Reader>()
and this to my configuration class
public override bool IsDiscriminated(Type type)
{
//this line indicates that the readers heirarchy should be all in one table, instead of seperate tables for every type of reader
bool ret = type.IsSubclassOf(typeof(Domain.Reader)) || type == typeof(Domain.Reader) ;
return ret;
}
(BTW, the example given in Fluent nHibernate's site uses the method "type.In(..." which does not exist in .net 3.5...)
that worked fine.
hopes this helps...

Fluent NHibernate mixed mapping properties

I'm trying to use fluent nhibernate to auto map most properties of a class, and then manually map 1 or 2 properties of that same class (without having to manually map all the other variables in the class map).
I have a class with a couple of dozen properties, but one of those properties is a string which needs to be a long length.
Here's an example:
Person class has fields: ID, firstname, lastname, description, and a few dozen other fields.
I would auto map the class but I want 'description' to be a long string, not a nvarchar(255).
So I try:
public class PersonMap : ClassMap
{
public PersonMap()
{
Map(x => x.description).Length(4000);
}
}
but this doesn't auto map all the other properties (an exception is thrown). It's expecting declarations for each property.
Is there a way to accomplish what I'm trying to do?
If anyone needs it, here's the code I'm using to declare the configuration:
FluentConfiguration cfg = Fluently.Configure()
.Database(FluentNHibernate.Cfg.Db.MsSqlConfiguration.MsSql2000.ConnectionString(Cn));
AutoPersistenceModel mdl =
AutoMap.Assembly(System.Reflection.Assembly.GetExecutingAssembly());
cfg.Mappings(m => m.AutoMappings.Add(mdl.Where(type =>
type.Namespace != null && type.Namespace.ToLower() == strNamespace.ToLower() )));
Thanks!
Ok I figured it out. There's a method called 'override' that I can use when declaring the configuration, and in there I can specify all the overrides for specific properties:
AutoPersistenceModel mdl = AutoMap.Assembly(System.Reflection.Assembly.GetExecutingAssembly());
mdl.Override<MyNamespace.Person>(map =>
{
map.Map(x => x.description).Length(4000);
});

Automapping doesn't have an Id mapped

My Entity Class:
public class Building
{
/// <summary>
/// internal Id
/// </summary>
public virtual long Id { get; set; }
..............
}
My Mapping:
var model = AutoMap.AssemblyOf<Building>()
.Setup(s => s.FindIdentity = p => p.Name == "Id")
.Where(t => t.Namespace == "SpikeAutoMappings");
var database = Fluently.Configure()
.Database(DatabaseConfigurer)
.Mappings(m=>m.AutoMappings.Add(model));
I need somebody to help me see what is wrong because I keep having this error when run unit test:
Initialization method TestProject1.MappingTestBase.TestInitialize threw exception. FluentNHibernate.Cfg.FluentConfigurationException: FluentNHibernate.Cfg.FluentConfigurationException: An invalid or incomplete configuration was used while creating a SessionFactory. Check PotentialReasons collection, and InnerException for more detail.
---> FluentNHibernate.Visitors.ValidationException: The entity doesn't have an Id mapped. Use the Id method to map your identity property. For example: Id(x => x.Id)..
both answers above are right; unless you specify differently, the automapper assumes that you have an int Id field.
If your Id is long, the automapper might not recognize it correctly.
try defining a MappingOverride for your class(es), like so:
public class UserMappingOverride : IAutoMappingOverride<User>
{
#region IAutoMappingOverride<User> Members
public void Override(AutoMapping<User> mapping)
{
mapping.Id(u => u.Name);
}
#endregion
}
the Id() function allows you to override the automapper's convention of what the ID field should be.
for further info on overriding, see http://wiki.fluentnhibernate.org/Auto_mapping#Overrides.
Cheers,
Jhonny
Generally, using AutoMapping is a poor policy because the filed Id must exist in your database tables. Instead, consider using a fluent mapping generator, such as NMG to handle your mapping.
In this case, you would first want to download/install the application, then generate the Mapping Files from your database (Oracle, SQL and various others).
In order to create the Mapping Files, first create an /Entities/ folder within your project. Next, configure the generator software as follows:
Preferences
Generated Property Name = Same as database column name (No change)
Mapping Style = Fluent Mapping
Field or Property = Auto Property
Languages available: C# and VB
Folder : [your project folder]\Entities
Namespace : [your project namespace].Entities
Assembly Name: [your project name].Entities
Next, either Generate All or Generate the Specific Table.
All of the *.cs and *Map.cs files should now be created in your project (you can add them with Add Existing Item... if they don't show up).
Using Fluent, you will see something like the following:
Id(x => x.keyName_ID)
.Column(x => x.keyname_ID)
.GeneratedBy
.Sequence("keyname_ID")
or
Id(x => x.keyName_ID)
.Column(x => x.keyname_ID)
.GeneratedBy
.Identity()
.Column("keyname_ID")
or
Id(x => x.keyName_ID)
.Column(x => x.keyname_ID)
.GeneratedBy
.Assigned()
So, now we need to specify the Id using FluentMapping with Fluent nHibernate. To do this, you need to overwrite the Id line of on code in each of the Map files in the solution. Simply add:
Id(x => x.KeyName_ID)
.GeneratedBy
.GetGeneratorMapping()
.IsSpecified("KeyName_ID");
Where keyname_id is the column name of the id in your database, rather than the one created.
Notice that in your mapping at the BuildSession you must have:
(...).Mappings(m =>
m.FluentMappings.AddFromAssemblyOf<[one of your entities]>()
);
And, now Id is mapped. :) I hope this helps!
My experience with Automapping is that as long as your Entity class has the line:
public virtual int Id { get; private set; }
the automapper will treat it as an ID with no further help from the programmer (i.e. no need for the FindIdenity code you are using in your AutoMap call).
The only difference I see in your ID declaration is that you use a type long instead of int. Don't know if this matters or not.

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();