I am trying to use FluentNHibernate AutoMappings to create an entity with reference to its parent. I was able to do this with help of ClassMap<>, but now I want to move everything to AutoMappings. I have a table with the following schema:
CREATE TABLE [dbo].[Job]
(
[Id] INT NOT NULL IDENTITY(1,1),
[ParentId] INT NULL,
PRIMARY KEY ([Id]),
CONSTRAINT [FK_Job_Parent] FOREIGN KEY ([ParentId]) REFERENCES [Job]([Id])
)
And the following C# code:
using FluentNHibernate;
using FluentNHibernate.Automapping;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using FluentNHibernate.Conventions;
using FluentNHibernate.Conventions.Instances;
using System;
using System.Configuration;
namespace NHibernateTest
{
public class Program
{
private static void Main(string[] args)
{
var sessionFactory = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008.ConnectionString(ConfigurationManager.ConnectionStrings["Default"].ConnectionString))
.Mappings(m =>
{
m.AutoMappings.Add(
AutoMap.AssemblyOf<Program>(new MappingConfig()).Conventions.Setup(conv =>
{
conv.Add<DefaultReferenceConvention>();
conv.Add<DefaultHasManyConvention>();
conv.Add<SimpleForeignKeyConvention>();
}));
})
.BuildSessionFactory();
using (var session = sessionFactory.OpenSession())
{
using (var tran = session.BeginTransaction())
{
var jobs = session
.QueryOver<Job>()
.List<Job>();
tran.Commit();
}
}
}
}
public class Job
{
public virtual int Id { get; set; }
public virtual Job Parent { get; set; }
}
public class MappingConfig : DefaultAutomappingConfiguration
{
public override bool ShouldMap(Type type)
{
return type == typeof(Job);
}
}
public class SimpleForeignKeyConvention : ForeignKeyConvention
{
protected override string GetKeyName(Member property, Type type)
{
if (property == null)
{
return type.Name + "Id";
}
return property.Name + "Id";
}
}
public class DefaultHasManyConvention : IHasManyConvention
{
public void Apply(IOneToManyCollectionInstance instance)
{
instance.Key.Column(string.Format("{0}{1}", instance.EntityType.Name, "Id"));
instance.LazyLoad();
}
}
public class DefaultReferenceConvention : IReferenceConvention
{
public void Apply(IManyToOneInstance instance)
{
var col = string.Format("{0}Id", instance.Class.Name);
instance.Column(col);
instance.LazyLoad();
}
}
}
I am getting:
An invalid or incomplete configuration was used while creating a SessionFactory. Check PotentialReasons collection, and InnerException for more detail.
Foreign key (FK7D5D63A6AE42E0BA:Job [JobId, ParentId])) must have same number of columns as the referenced primary key (Job [Id])
Is there a way to do this using auto mappings only?
Your DefaultReferenceConvention
appears to conflict with your SimpleForeignKeyConvention
. One of them uses the property name as the basis for the column name, the other uses the property type . It looks like for some reason Fluent NH is using both of these, and thinks you have a composite key.
Remove DefaultReferenceConvention
and see if that fixes it. It's unnecessary anyway because Fluent NH's default foreign key column naming is already {Class.Name}Id
.
Fluent NH conventions are excellent for painting your mappings with broad brush strokes, but they are not the right tool for changing the column name of a single property. In that case, you should define an IAutoMappingOverride<T>
instead.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.