NHibernate — присвоить столбцу внешнего ключа значение null при удалении

#c# #nhibernate #fluent-nhibernate #foreign-keys

#c# #nhibernate #свободно-nhibernate #внешние ключи

Вопрос:

У меня есть две сущности, EntityA и EntityB. EntityB может необязательно быть связан с EntityA и имеет столбец внешнего ключа, который можно обнулить. Когда EntityA удаляется, я хочу, чтобы внешнему ключу в EntityB было присвоено значение null.

Поэтому, когда я удаляю EntityA, я бы хотел, чтобы он устанавливал внешний ключ в любых ссылочных EntityBs перед выдачей команды УДАЛЕНИЯ. Я видел, как NHibernate делал это раньше «случайно», и теперь, когда я действительно хочу, чтобы он это сделал, я, похоже, не могу понять это правильно. Лучшее, что я смог сделать, это удалить EntityB после его потери, чего я не хочу. Конечно, я мог бы установить ограничение внешнего ключа в SQL Server, чтобы установить для столбца значение null, но я чувствую, что NHibernate должен уметь это делать. Аналогично, я мог бы перебрать все EntityB, на которые ссылается удаляемая EntityA, и присвоить им значение null. Опять же, почему я должен это делать?

Вот мои сущности и сопоставления:

 public class EntityA : Entity // Entity contains the ID property and implements GetHashCode() and Equals()
{
    // irrelevant properties

    public virtual IList<EntityB> EntityBs { get; protected set; }
}

public class EntityB : Entity
{
    // irrelevant properties
    public virtual EntityA EntityA { get; set; }
}


public class EntityAMap: ClassMap<EntityA>
{
    public EntityAMap()
    {
         HasMany(c => c.EntityBs)
             .ForeignKeyConstraintName("FK_EntityA_EntityB")
         .KeyColumn("EntityA_Id")
             .Inverse()
             .Cascade.None(); // i've tried other cascade settings with little luck
    }   
}

public class EntityBMap: ClassMap<EntityB>
{
    public EntityBMap()
    {
         References(c => c.EntityA)
             .Nullable()
             .Column("EntityA_Id")
             .ForeignKey("FK_EntityA_EntityB")
             .Index("IX_EntityB_EntityA_Id")
             .Cascade.None();
    }   
}
  

Затем я удаляю следующим образом:

 var entityA = Repository.Get(idToDelete);
// entityA.EntityBs.Clear(); // tried this, no affect
Repository.Remove(entityA);

Repository.Flush(); // is it possible this isn't working because I'm missing a Tx?
  

Результатом является нарушение ограничения внешнего ключа, поскольку EntityB.EntityA_Id не обнуляется.

Комментарии:

1. Вы пробовали устанавливать для hasmany значение KeyNullable().Cascade.All() ?

Ответ №1:

Вам нужно сделать что-то вроде:

 entityA.EntityBs.ToList().ForEach(b => b.EntityA = null );

Repository.Remove(entityA);
Repository.Flush();
  

Если какие-либо B все еще ссылаются на A, вы не можете удалить A, особенно без каскадирования.

Комментарии:

1. да, я понимаю, что это один из вариантов. мне кажется, что я видел, как nhibernate обрабатывал это в прошлом, и я хотел бы посмотреть, является ли это просто вопросом правильного сопоставления, прежде чем я применю грубую силу.

Ответ №2:

Вы должны установить для всех каскадов значение none, а затем .inverse() в EntityBMap. Пожалуйста, дайте мне отзыв, если это сработает.

Mariusz