【问题标题】:How to reference parent entity in the same table with fluent nhibernate auto mappings?如何使用流畅的 nhibernate 自动映射引用同一张表中的父实体?
【发布时间】:2015-07-21 08:30:44
【问题描述】:

我正在尝试使用 FluentNHibernate AutoMappings 来创建一个参照其父实体的实体。我能够在 ClassMap 的帮助下做到这一点,但现在我想将所有内容移至 AutoMappings。我有一个具有以下架构的表:

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]) 
)

以及以下 C# 代码:

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

我得到:

创建 SessionFactory 时使用了无效或不完整的配置。查看PotentialReasons 集合和InnerException 了解更多详情。

外键 (FK7D5D63A6AE42E0BA:Job [JobId, ParentId])) 必须与引用的主键 (Job [Id]) 具有相同的列数

有没有办法只使用自动映射来做到这一点?

【问题讨论】:

    标签: c# nhibernate fluent-nhibernate fluent-nhibernate-mapping


    【解决方案1】:

    您的DefaultReferenceConvention 似乎与您的SimpleForeignKeyConvention 冲突。其中一个使用属性name 作为列名的基础,另一个使用属性type。看起来出于某种原因,Fluent NH 正在使用 both 这两种方法,并认为您有一个复合键。

    删除DefaultReferenceConvention 看看是否能解决问题。反正没必要,因为 Fluent NH 的默认外键列命名已经是 {Class.Name}Id

    Fluent NH 约定非常适合使用广泛的笔触绘制映射,但它们不是更改单个属性的列名称的正确工具。在这种情况下,您应该改为定义 IAutoMappingOverride&lt;T&gt;

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-11-14
      • 1970-01-01
      • 2011-03-13
      • 1970-01-01
      • 2011-01-28
      • 1970-01-01
      • 2011-08-12
      • 1970-01-01
      相关资源
      最近更新 更多