Многие ко многим и пакетное удаление HQL - PullRequest
2 голосов
/ 26 февраля 2011

У меня есть две сущности с определенными отношениями «многие ко многим».

<set name="TreasuryCodes" table="ServiceProviderAccountTreasuryCode" lazy="true" cascade="all">
  <key column="ServiceProviderAccountId" />
  <many-to-many column="TreasuryCodeId" class="TreasuryCode" />
</set>

<set name="ServiceProviderAccounts" table="ServiceProviderAccountTreasuryCode" lazy="true" inverse="true" cascade="all">
  <key column="TreasuryCodeId" />
  <many-to-many column="ServiceProviderAccountId" class="ServiceProviderAccount" />
</set>

Теперь я хочу удалить все учетные записи ServiceProvider по ServiceProviderId. Я пишу этот код:

    public void DeleteAllAccount(int serviceProviderId)
    {
        const string query = "delete ServiceProviderAccount spa where spa.ServiceProvider.Id = :serviceProviderId";
        repository.Session.CreateQuery(query)
            .SetInt32("serviceProviderId", serviceProviderId)
            .ExecuteUpdate();
        repository.Session.Flush();
    }

и я получаю это исключение:

Test method Test.ServiceRepositoryTest.DeleteAllAccountTest threw exception: 
NHibernate.Exceptions.GenericADOException: could not execute update query[SQL: delete from ServiceProviderAccount where ServiceProviderId=?] ---> System.Data.SqlClient.SqlException: The DELETE statement conflicted with the REFERENCE constraint "FKBC88A84CB684BF79". The conflict occurred in database "Test", table "dbo.ServiceProviderAccountTreasuryCode", column 'ServiceProviderAccountId'.
The statement has been terminated.

Я запутался, так как я определил каскад для сущности, не должен ли nhibernate удалять строки из ServiceProviderAccountTreasuryCode?

UPDATE


хорошо, похоже, ExecuteUpdate не ищет каскад NHibernate, возможно, потому, что он не загружает объекты перед его удалением? В любом случае, есть ли другой способ удаления из таблицы ServiceProviderAccountTreasuryCode, а затем из ServiceProviderAccounts через HQL? Я знаю, что могу использовать каскады в базе данных, но я хочу этого избежать. Я хочу удалить строки из таблицы сопоставления «многие ко многим» с помощью HQl. Является ли это возможным? Или я должен использовать простой SQL?

Ответы [ 2 ]

3 голосов
/ 27 февраля 2011

выглядит так, как будто у вас есть проблема ссылочной целостности, т. Е. Связь между ключами foregin, где на удаляемый вами идентификатор ссылается где-то еще, и эта таблица в конечном итоге ничего не ссылается. если это то, что вы хотите сделать, то вы можете запустить команду Truncate , но я не уверен, почему вы это сделаете ..

Я бы посоветовал вам сделать обычное удаление, т.е. с помощью сеанса nhibernate и Linq, как показано ниже:

 foreach(var sessionProvider in Session.Linq<ServiceProviderAccount >().Where(x=>x.ServiceProvider.Id==servinceProviderId))
       Session.Delete(sessionProvider);

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

Надеюсь, что это работает ..

0 голосов
/ 27 февраля 2011

Похоже, он не подчиняется каскадированию. Пакетные операции HQL для обновления / удаления являются относительно новыми и переводят более или менее непосредственно в SQL. Я считаю, что вы также должны отслеживать соответствующие таблицы.

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

Я задал похожий вопрос, ответ, который я получил, может вас заинтересовать

Удалить сущность в NHibernate только по первичному ключу

...