NHibernate поведение многих ко многим на БД - PullRequest
0 голосов
/ 22 мая 2018

У нас есть классы Bar и Foo, у них простое отношение «многие ко многим»:

public partial class Bar
{
    public virtual Guid BarId { get; set; } = Guid.Empty;
    public virtual IList<Foo> ManyBarsInManyFoos { get; protected set; } = new Collection<Foo>();
}

public partial class Foo
{
    public virtual Guid FooId { get; set; } = Guid.Empty;
    public virtual IList<Bar> ManyFoosInManyBars { get; protected set; } = new Collection<Bar>();
}

Вначале я использовал сумку, чтобы отобразить это «многие ко многим»:

  <class name="Bar" table="Bars" optimistic-lock="version">
    <id name="BarId" unsaved-value="{00000000-0000-0000-0000-000000000000}">
      <generator class="guid" />
    </id>
    <timestamp name="LastChange" />
    <bag name="ManyBarsInManyFoos" table="ManyBarsInManyFoos" cascade="save-update" inverse="false">
      <key column="ManyBarsInManyFoosBarId" />
      <many-to-many column="ManyFoosInManyBarsFooId" class="Many2Many.DomainModel.Foo" />
    </bag>
  </class>

  <class name="Foo" table="Foos" optimistic-lock="version">
    <id name="FooId" unsaved-value="{00000000-0000-0000-0000-000000000000}">
      <generator class="guid" />
    </id>
    <timestamp name="LastChange" />
    <bag name="ManyFoosInManyBars" table="ManyBarsInManyFoos" cascade="save-update" inverse="false">
      <key column="ManyFoosInManyBarsFooId" />
      <many-to-many column="ManyBarsInManyFoosBarId" class="Many2Many.DomainModel.Bar" />
    </bag>
  </class>

Это прекрасно работает, но мы обнаружили, что при удалении одной ассоциации (одной строки в таблице ManyBarsInManyFoos) NHibernate удаляет все строки, связанные с этим BarId, а затем повторно вставляет другие строки:

'UPDATE dbo.Bars SET LastChange = @p0 WHERE BarId = @p1 AND LastChange = @p2',N'@p0 datetime,@p1 uniqueidentifier,@p2 datetime',@p0='2018-05-22 17:22:17.760',@p1='F111C29E-41C1-483F-AC28-053A53713A10',@p2='2018-05-22 17:21:44.410'
'UPDATE dbo.Foos SET LastChange = @p0 WHERE FooId = @p1 AND LastChange = @p2',N'@p0 datetime,@p1 uniqueidentifier,@p2 datetime',@p0='2018-05-22 17:22:17.760',@p1='5204C39B-265F-47F7-AA30-2D104A6FCEFB',@p2='2018-05-22 17:21:44.440'
'DELETE FROM dbo.ManyBarsInManyFoos WHERE ManyBarsInManyFoosBarId = @p0',N'@p0 uniqueidentifier',@p0='F111C29E-41C1-483F-AC28-053A53713A10'
'INSERT INTO dbo.ManyBarsInManyFoos (ManyBarsInManyFoosBarId, ManyFoosInManyBarsFooId) VALUES (@p0, @p1)',N'@p0 uniqueidentifier,@p1 uniqueidentifier',@p0='F111C29E-41C1-483F-AC28-053A53713A10',@p1='D1A635A0-360D-4AC1-98EE-EE3CE47BE63C'
'INSERT INTO dbo.ManyBarsInManyFoos (ManyBarsInManyFoosBarId, ManyFoosInManyBarsFooId) VALUES (@p0, @p1)',N'@p0 uniqueidentifier,@p1 uniqueidentifier',@p0='F111C29E-41C1-483F-AC28-053A53713A10',@p1='58EA2B80-C8D9-4708-90D7-FA110816715B'
'DELETE FROM dbo.ManyBarsInManyFoos WHERE ManyFoosInManyBarsFooId = @p0',N'@p0 uniqueidentifier',@p0='5204C39B-265F-47F7-AA30-2D104A6FCEFB'
'INSERT INTO dbo.ManyBarsInManyFoos (ManyFoosInManyBarsFooId, ManyBarsInManyFoosBarId) VALUES (@p0, @p1)',N'@p0 uniqueidentifier,@p1 uniqueidentifier',@p0='5204C39B-265F-47F7-AA30-2D104A6FCEFB',@p1='B67DE063-BFD9-4AE3-BADA-2B3B5669295D'
'INSERT INTO dbo.ManyBarsInManyFoos (ManyFoosInManyBarsFooId, ManyBarsInManyFoosBarId) VALUES (@p0, @p1)',N'@p0 uniqueidentifier,@p1 uniqueidentifier',@p0='5204C39B-265F-47F7-AA30-2D104A6FCEFB',@p1='0DB243BC-3C89-43E0-AD55-C0CD8120E711'

Кажется, что это поведение необходимо для обработки нескольких связей между одними и теми же объектами в сумке, которые не индексируются.Но нам нужно (из-за триггера или чего-то подобного), чтобы существующие строки «многие ко многим» в таблице ManyBarsInManyFoos не удалялись (кроме тех, которые действительно связаны с удаленным отношением).

Первый вопрос: Есть ли способ избежать этого "массового" удаления и сказать NHibernate об удалении только соответствующей строки?

Думая, что, вероятно, это невозможно, я пытался использовать список вместо сумка :

<list name="ManyBarsInManyFoos" table="ManyBarsInManyFoos" cascade="save-update">
  <key column="ManyBarsInManyFoosBarId" />
  <index column="Position"/>
  <many-to-many column="ManyFoosInManyBarsFooId" class="Many2Many.DomainModel.Foo" />
</list>
-------
<list name="ManyFoosInManyBars" table="ManyBarsInManyFoos" cascade="save-update" inverse="true">
  <key column="ManyFoosInManyBarsFooId" />
  <index column="Position"/>
  <many-to-many column="ManyBarsInManyFoosBarId" class="Many2Many.DomainModel.Bar" />
</list>

но некоторые вещи становятся немного более странными (для меня) при удалении существующей ассоциации:

'UPDATE dbo.Bars SET LastChange = @p0 WHERE BarId = @p1 AND LastChange = @p2',N'@p0 datetime,@p1 uniqueidentifier,@p2 datetime',@p0='2018-05-22 17:56:46.480',@p1='301E92EA-5E37-4948-A0FE-00884D5EB221',@p2='2018-05-22 17:56:32.180'
'DELETE FROM dbo.ManyBarsInManyFoos WHERE ManyBarsInManyFoosBarId = @p0 AND Position = @p1',N'@p0 uniqueidentifier,@p1 int',@p0='301E92EA-5E37-4948-A0FE-00884D5EB221',@p1=2
'UPDATE dbo.ManyBarsInManyFoos SET ManyFoosInManyBarsFooId = @p0 WHERE ManyBarsInManyFoosBarId = @p1 AND Position = @p2',N'@p0 uniqueidentifier,@p1 uniqueidentifier,@p2 int',@p0='CE0C01A3-4F0E-4E93-A33C-22AAE68482D9',@p1='301E92EA-5E37-4948-A0FE-00884D5EB221',@p2=0
'UPDATE dbo.ManyBarsInManyFoos SET ManyFoosInManyBarsFooId = @p0 WHERE ManyBarsInManyFoosBarId = @p1 AND Position = @p2',N'@p0 uniqueidentifier,@p1 uniqueidentifier,@p2 int',@p0='193C5714-FD1C-4C51-AD5F-6B19F262046F',@p1='301E92EA-5E37-4948-A0FE-00884D5EB221',@p2=1

Другие строки не удаляются, но могут быть «использованы повторно» и «переключены» за кулисы от объекта к другому.Неправильное решение.

Наконец, я попытался использовать map ... Пробовал, но не смог понять, как создать правильные теги сопоставления для этой простой взаимосвязи.

Следовательно, второй вопрос: Как я могу сопоставить это «многие ко многим» с тегом map ?И / или как мы можем оптимизировать это отношение «многие ко многим» оптимизированным способом, используя NHibernate для простого удаления одной задействованной строки в таблице ManyBarsInManyFoos, вместо удаления многих строк для их повторной вставки через некоторое время или «переназначения» строк отношения дляразные предметы?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...