我的自定义ForeignKeyConvention导致创建两个外键而不是一个

时间:2011-09-27 06:36:45

标签: nhibernate fluent-nhibernate fluent-nhibernate-mapping

我正在尝试创建自己的外键约定,它将以“ FK_SourceTable_TargetTable ”格式命名FK。

然而,当我运行它时,我最终使用两个外键而不是一个。

我的自定义外键约定如下所示:

public class OurForeignKeyConvention : ForeignKeyConvention
{
    protected override string GetKeyName(Member property, Type type)
    {
        if (property == null)
            return string.Format("FK_{0}Id", type.Name); // many-to-many, one-to-many, join
        if (property.Name == type.Name)
            return string.Format("FK_{0}_{1}", property.DeclaringType.Name, type.Name);
        return string.Format("FK_{0}_{1}_{2}", property.DeclaringType.Name, property.Name, type.Name);
    }
}

我的代码来运用它:

    [TestMethod]
    public void ShouldBeAbleToBuildSchemaWithOurConventions()
    {
        var configuration = new Configuration();
        configuration.Configure();
        Fluently
            .Configure(configuration)
            .Mappings(m => m.FluentMappings
                .AddFromAssemblyOf<Widget>()
                .Conventions.Add<OurForeignKeyConvention>()
                )
            .BuildSessionFactory();
        new SchemaExport(configuration).Create(false, true);
    }

我的课程和映射:

public class Widget
{
    public virtual int Id { get; set; }
    public virtual string Description { get; set; }
    public virtual WidgetType Type { get; set; }
    public virtual ISet<WidgetFeature> Features { get; set; } 
}

public class WidgetFeature
{
    public virtual int Id { get; set; }
    public virtual Widget Widget { get; set; }
    public virtual string FeatureDescription { get; set; }
}

public class WidgetMap : ClassMap<Widget>
{
    public WidgetMap()
    {
        Id(w => w.Id);
        Map(w => w.Description);
        HasMany(w => w.Features).Cascade.AllDeleteOrphan().Inverse();
    }
}

public class WidgetFeatureMap : ClassMap<WidgetFeature>
{
    public WidgetFeatureMap()
    {
        Id(w => w.Id);
        Map(w => w.FeatureDescription);
        References(w => w.Widget);
    }
}

最终结果是两个外键,一个叫做我想要的 - FK_WidgetFeature_Widget - 另一个叫做 FK_WidgetId

如果我将OurForeignKeyConvention更改为始终返回相同的名称,无论“property”参数是否为null,那么我正确地获得单个FK - 但我无法获得“ SourceTable ”部分FK名称。

有谁能解释我在这里做错了什么?为什么GetKeyName被调用两次?为什么其中一个调用没有为“property”参数提供值?

1 个答案:

答案 0 :(得分:1)

卫生署。 ForeignKeyConvention提供FK列的名称。我应该使用的是IHasManyConvention,它可以用来命名FK约束本身。

public class OurForeignKeyConstraintNamingConvention : IHasManyConvention
{
    public void Apply(IOneToManyCollectionInstance instance)
    {
        instance.Key.ForeignKey(string.Format("FK_{0}_{1}", instance.Relationship.Class.Name, instance.EntityType.Name));
    }
}