Каскад не работает, как я ожидаю - PullRequest
1 голос
/ 17 мая 2011

Я относительно новичок в настройке NHibernate и столкнулся с проблемой.У меня есть следующие объекты:

public class Report
{
    public virtual int Id { get; private set; }
    public virtual string Name { get; private set; }
    public virtual string Path { get; private set; }
    public virtual string Alias { get; private set;}

    public virtual IList<Tab> Tabs
    {
        get; private set;
    }
}

public class Tab
{
    public virtual string Name { get; private set; }
    public virtual string Description { get; private set; }
    public virtual IList<Section> Sections { get; set; }
    public virtual Report ParentReport { get; private set; }
}

public class Section
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
}

Я использую Fluent NHibernate и Auto Mapping для сопоставления отношений.

.Database(MsSqlConfiguration.MsSql2005.ShowSql().ConnectionString(c => c.Is(connectionString)))                
.Mappings(map => map.AutoMappings.Add(AutoMap.AssemblyOf<Workbook>(configuration)
.Conventions.AddFromAssemblyOf<CascadeAll>()

Проблема в том, что независимо от того, какие параметры каскада я выберу в своем классе CascadeAll, я не могу заставить его работать так, как мне хотелось бы.

Когда я удаляю вкладку из данного отчета, я хочу удалить разделы на вкладке из базы данных, а затем удалить вкладку из отчета в базе данных.

Cascade.All()

Удаляет связь между отчетом и вкладкой, но при этом значение параметра ParentReport_id для сироты устанавливается равным нулю.

Cascade.AllDeleteOrphan() 

При этом удаляются все разделы, вкладки, связанные с отчетом, а затем удаляется отчет, несмотря на удаление только одной вкладки из коллекции в отчете.

Cascade.SaveUpdate() 

Действует как Всев том, что это orhpans вкладка.

Между прочим, все они вызываются путем удаления вкладки из коллекции вкладок в Report и последующего вызова session.SaveUpdate (instance)> Где instance - обновляемый экземпляр Report.

Есть идеи, как мне это исправить или что я делаю не так?

Ответы [ 2 ]

1 голос
/ 19 мая 2011

Спасибо, Рекс, я подозреваю, что твое предложение сработает, так что я могу попробовать. Это было полностью связано с отношением между отчетом и вкладкой, вызвав OneToMany (отчет-> вкладка) и ManyToOne (вкладка -> отчет). С выбранными каскадными опциями он либо обнулит внешний ключ, либо удалит вкладку, все остальные вкладки и отчет. Это было с AllDeleteOrphan.

Когда я удаляю взаимосвязь Tab -> Report ManyToOne, запись об удаленных файлах удаляется без повторного удаления Repotr. В конце я выбрал быстрый вариант создания файла явного сопоставления, в котором использовался HasMany (x => x.Tabs) .... в файле ReportMapping & References (x => x.ParentReport) ... в TabMapping ,

Спасибо за вашу помощь.

0 голосов
/ 17 мая 2011

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

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

Полагаю, вы захотите использовать .AllDeleteOrphan() для своей коллекции Sections и .All() для своей коллекции Tabs.

В вашем случае, я считаю, что ваше переопределение будет выглядеть примерно так.

public class ReportMappingOverride : IAutoMappingOverride<Report>
{
    public void Override(AutoMapping<Report> mapping)
    {
        // You don't need this, but I'll leave it for an example...
        //mapping.HasMany(x => x.Tabs).Cascade.All();
    }
}

public class TabMappingOverride : IAutoMappingOverride<Tab>
{
    public void Override(AutoMapping<Tab> mapping)
    {
        // You don't need this, but I'll leave it for an example...
        //mapping.HasMany(x => x.Sections).Cascade.AllDeleteOrphan();
        // This should prevent deletes from being cascaded to the Report
        //   (which would delete the report).
        mapping.References(x => x.ParentReport).Cascade.SaveUpdate();
    }
}

Чтобы использовать переопределения, ваш конфиг немного изменится и будет выглядеть примерно так:

.Mappings(map => map.AutoMappings.Add(AutoMap.AssemblyOf<Workbook>(configuration).UseOverridesFromAssemblyOf<ReportMappingOverride>()

Возвращение свойства к родительскому отчету не должно иметь значения, но для тестирования вы можете вынуть его и посмотреть, не в этом ли проблема.

...