使用NHibernate的唯一复合索引

时间:2012-08-03 14:53:02

标签: nhibernate fluent-nhibernate

NHibernate阻止我在使用单向关联时拥有由外键和列组成的唯一索引。

//The classes
public class Method
{
    public virtual Guid ID { get; private set; }
    public virtual List<MethodParameter> Parameters { get; private set; }

    public Method()
    {
        this.Parameters = new List<MethodParameter>();
    }
}

public class MethodParameter
{
    public virtual Guid ID { get; private set; }
    public virtual string Name { get; private set; }

    protected MethodParameter() { }

    public MethodParameter(Method method, string name)
    {
        this.Name = name;
        method.Parameters.Add(this);
    }
}

//The mappings
public class MAP_Method : ClassMap<Method>
{
    public MAP_Method()
    {
        this.Table("[Method]");
        this.Id(x => x.ID).Access.BackingField().GeneratedBy.GuidComb();
        this.HasMany(x => x.Parameters)
            .Access.BackingField()
            .KeyColumn("[Method]")
            .Not.LazyLoad()
            .Cascade.AllDeleteOrphan();
    }
}

public class MAP_MethodParameter : ClassMap<MethodParameter>
{
    public MAP_MethodParameter()
    {
        this.Table("[MethodParameter]");
        this.Map(x => x.Name).Length(50).Not.Nullable();
    }
}

如果我用两个MethodParameters(Name:x和Name:y)创建一个Method实例,那么没有问题。但是,如果我在具有相同MethodParameter名称的同一事务中创建两个Method实例,那么我将获得唯一的索引违规。

这是因为我在[MethodParameter]([Method] ASC,[Name] ASC)上有一个唯一索引,并且单向关联NHibernate首先为[Method]列插入带有NULL的子表,然后去返回并使用正确的[Method]值更新行。

显然,当插入两个具有相同MethodParameter名称的Method实例时,这是一个问题,因为我最终得到(null,“x”)(null,“x”)而不是(Method1,“x”)(Method2,“ X“)

我知道这是设计的行为,但似乎我被迫要么具有双向逆关联,要么从DB中删除唯一索引。有没有办法让NHibernate在插入时插入正确的[Method] ID,而不是插入NULL然后更新?

1 个答案:

答案 0 :(得分:1)

由于您的关联是单向的,因此您必须设置以下选项:inverse="false"关联(<one-to-many>),not-null="true"关键(<key>)。如果您不打算更改参数的所有者,则必须在密钥(update="false")上设置<key>

它将阻止向FK列插入null。

FluentNHibernate示例:

this.HasMany(x => x.Parameters)
    .Not.Inverse()     // 1
    .Not.KeyNullable() // 2
    .Not.KeyUpdate()   // 3
    .Access.BackingField()
    .KeyColumn("[Method]")
    .Not.LazyLoad()
    .Cascade.AllDeleteOrphan();

请查看以下答案,以获得更好的解释https://stackoverflow.com/a/7601312/259946https://stackoverflow.com/a/11576097/259946