I have a IIdConvention for my Fluent NHibernate mapping:
public class SplitIDNameConvention : IIdConvention
{
public bool Accept(IIdentityPart target)
{
return true;
}
public void Apply(IIdentityPart target)
{
if (target.GetColumnName() == null)
target.ColumnName(SplitName(target.Property.Name));
}
}
This works perfect for tables with a single primary key, but I have a lot of tables with CompositeKeys. Is there a way to provide a Convetion which changes the mapped column name for CompositeIds in Fluent NHibernate?
Best regards,
forki
Not what you want to hear, but no, not currently.
Related
My database has multiple schemas, the fluent nhibernate faq states that you can specify schema for the entire database, or per entity. I want to specify schema per AutoPersitenceModel, can this be done?
Got it:
public class SchemaConvention : IClassConvention
{
public void Apply(IClassInstance instance)
{
instance.Schema("schemaName");
}
}
AutoPersistenceModel model = AutoMap.AssemblyOf<Whatever>();
model.Conventions.AddFromAssemblyOf<SchemaConvention>();
I'm creating a little application using Sharp Architecture, and I've run into a bug I can't figure out. I think it has something to do with the NHibernte mappings. In my HttpPost Create() method, my SaveOrUpdate call is trying to insert null into the table's primary key field. The declaration for the primary key in my model is public virtual int Id { get; protected set; }.
I checked newSprint.Id and it's zero. I think the problem's with my NHibernate Mappings, so I've included all of that below.
Here's the automapping configuration:
public class AutomappingConfiguration : DefaultAutomappingConfiguration
{
public override bool ShouldMap(System.Type type)
{
return type.GetInterfaces().Any(x =>
x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IEntityWithTypedId<>));
}
public override bool ShouldMap(Member member)
{
return base.ShouldMap(member) && member.CanWrite;
}
public override bool AbstractClassIsLayerSupertype(System.Type type)
{
return type == typeof(EntityWithTypedId<>) || type == typeof(Entity);
}
public override bool IsId(Member member)
{
return member.Name == "Id";
}
}
The auto-persistence model generator:
public class AutoPersistenceModelGenerator : IAutoPersistenceModelGenerator
{
public AutoPersistenceModel Generate()
{
var mappings = AutoMap.AssemblyOf<Sprint>(new AutomappingConfiguration());
mappings.IgnoreBase<Entity>();
mappings.IgnoreBase(typeof(EntityWithTypedId<>));
mappings.Conventions.Setup(GetConventions());
mappings.UseOverridesFromAssemblyOf<AutoPersistenceModelGenerator>();
return mappings;
}
private static Action<IConventionFinder> GetConventions()
{
return c =>
{
c.Add<PrimaryKeyConvention>();
c.Add<CustomForeignKeyConvention>();
c.Add<HasManyConvention>();
c.Add<TableNameConvention>();
};
}
Thanks in advance for any help anyone can offer.
Edit
I figured out that the problem was with the Table Name Convention. Removing that from the AutoMapping configuration solved the problem. I've removed the extraneous code and added the TableNameConvention mapping in the hopes that someone can explain what specifically about it caused those problems.
public class TableNameConvention : IClassConvention
{
public void Apply(FluentNHibernate.Conventions.Instances.IClassInstance instance)
{
instance.Table(Inflector.Net.Inflector.Pluralize(instance.EntityType.Name));
}
}
Your IdGenerator is probably not right. You need to set an appropriate generator for your PrimaryKey. For example, Identity if you're using SQL Server.
I'm not sure how you set this with your setup, not very familiar with Fluent NH. My guess is PrimaryKeyConvention?
I have a convention UserTypeConvention<MyUserType> where MyUserType : IUserType where MyUserType handles an enum type MyEnum. I have configured Fluent NHibernate thusly
sessionFactory = Fluently
.Configure()
.Database(MsSqlConfiguration.MsSql2005.ConnectionString(
c => c.Is(connectionString))
)
.Mappings(
m => m
.FluentMappings
.AddFromAssemblyOf<A>()
.Conventions
.AddFromAssemblyOf<A>()
)
.BuildSessionFactory();
where A is a type in the same assembly as UserTypeConvention<MyUserType> and MyUserType. However, Fluent NHibernate is not applying MyUserType to properties of type MyEnum on my domain objects. Instead, it is applying FluentNHibernate.Mapping.GenericEnumMapper<MyEnumType> to these properties.
What is going on?
For now I have solved this with:
public class MyEnumUserTypeConvention : UserTypeConvention<MyEnumUserType> {
public override void Accept(IAcceptanceCriteria<IPropertyInspector> criteria) {
// Fluent NHibernate is too eager in applying GenericEnumMapper
// so our criteria is that it is already applied this type
criteria.Expect(x => x.Type == typeof(GenericEnumMapper<MyEnum>));
}
public override void Apply(IPropertyInstance instance) {
// we override Fluent NHibernate's application of GenericEnumMapper
instance.CustomType<MyEnumUserType>();
}
}
I think this should be thoroughly unnecessary. If someone told me this were a bug in Fluent NHibernate, that'd be fine. If someone gave me a good reason why Fluent NHibernate should be so eager in applying GenericEnumMapper that would be acceptable too.
Ok i tried the following and I think it will works for you :
just overriede the Accept method in MyEnumUserTypeConvention class and do nothing inside it:
public class MyEnumUserTypeConvention : UserTypeConvention<MyEnumUserType>
{
public override void Accept(FluentNHibernate.Conventions.AcceptanceCriteria.IAcceptanceCriteria<FluentNHibernate.Conventions.Inspections.IPropertyInspector> criteria)
{
///Do nothing
}
}
i have the following class:
public class Worker
{
public int WorkerID {get;set;}
public string Name { get;set;}
}
public class TransferOrder
{
public int TransferOrderID { get;set;}
public Worker workerTobeTransfered{get;set;}
}
how do i automap this classes in fluent nhibernate.
ok, after a few googling, i figured out the solution:
this is a many-to-one relation and it is mapped using Reference() Method, and the auto mapping already do that:
References<Worker>(m => m.Worker);
there is also a great article provide many examples of mapping situations which can be found
Here.
In the project I'm working on now, we have base Entity class that looks like this:
public abstract class Entity<T> where T : Entity<T>
{
public virtual object Id { get; protected set }
// Equals, GetHashCode overrides, etc...
}
Most classes inheriting from Entity should map Id to int column in SQL Server database, but at least one will need to map to long (bigint).
Is it possible to create FluentNH Auto Mapping convention to map those object Ids to int by default? Then we could use another convention or IAutoMappingOverride to handle long Ids.
Thanks!
To answer my own question... It's possible.
You can define convention like this:
internal class PrimaryKeyConvention : IIdConvention
{
public bool Accept(IIdentityPart id)
{
return true;
}
public void Apply(IIdentityPart id)
{
if (<ID should be long>)
id.SetAttribute("type", "Int64");
else
id.SetAttribute("type", "Int32");
}
}