nHibernate пытается обновить SQL сущность, которую я только что создал, а не вставлять? - PullRequest
0 голосов
/ 29 мая 2019

Участник проекта может быть членом многих групп, а в группе может быть много участников проекта

Я обнаружил, что когда я создаю 2 участника ProjectParticipant (это работает), а затем заполняю коллекцию Project.Groups значением 3 новые группы и добавление участников в соответствующие группы (в группе A есть участник 1, в группе B есть участник 2, в группе C есть участники 1 и 2), я обнаружил «StaleStateException - пакетное обновление вернуло неожиданное количество строк изобновление; фактическое количество строк: 0, ожидаемое: 3 ".Я ожидаю, что nHibernate вставит новые группы, но он выполняет запрос UPDATE и предупреждает, что они не существуют.Это не так далеко, как назначение участников в группы

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

//ProjectMap: A Project..
        Id(x => x.Id).GeneratedBy.GuidComb().UnsavedValue(Guid.Empty);
        HasMany(x => x.Participants)
            .Table("ProjectParticipants")
            .KeyColumn("ProjectId")
            .ApplyFilter(DeletedDateFilter.FilterName)
            .Cascade.AllDeleteOrphan()
            .Inverse();

        HasMany(x => x.Groups)
            .Table("ProjectGroups")
            .KeyColumn("ProjectId")
            .Cascade.AllDeleteOrphan()
            .Inverse();


//ProjectParticipantMap: A ProjectParticipant…
        Id(x => x.Id).GeneratedBy.GuidComb().UnsavedValue(Guid.Empty);
        References(x => x.Project)
            .Column("ProjectId")
            .LazyLoad(Laziness.Proxy);
        HasManyToMany(x => x.Groups)
            .Table("ProjectGroupParticipants")
            .ParentKeyColumn("ProjectParticipantId")
            .ChildKeyColumn("ProjectGroupId");


//GroupMap: A Group...
        Id(e => e.Id).GeneratedBy.Assigned().UnsavedValue(Guid.Empty);
        References(e => e.Project)
            .Column("ProjectId")
            .LazyLoad(Laziness.Proxy);
        HasManyToMany(x => x.Participants)
            .Table("ProjectGroupParticipants")
            .ParentKeyColumn("ProjectGroupId")
            .ChildKeyColumn("ProjectParticipantId")
            .ApplyChildFilter(DeletedDateFilter.FilterName);

Таблицы:

[ProjectParticipants] 1-->M [ProjectGroupParticipants] M<--1 [ProjectGroups]
              M                                                   M
              \---------------->1 [Project] 1<--------------------/

ВотSQL, выполняемые nHibernate:

--presume this is adding the first participant - I find him in the db
INSERT INTO ProjectParticipants (CreatedDate, ModifiedDate, DeletedDate, FirstName, LastName, Timezone, Email, Pseudonym, Role, ProjectId, UserId, MobileNumber, Id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)

--presume this is adding the second participant - I find her in the DB
INSERT INTO ProjectParticipants (CreatedDate, ModifiedDate, DeletedDate, FirstName, LastName, Timezone, Email, Pseudonym, Role, ProjectId, UserId, MobileNumber, Id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)

--not sure what this is doing
UPDATE Projects SET CreatedDate = ?, ModifiedDate = ?, LogoUrl = ?, LogoFilename = ?, Client = ?, Name = ?, Description = ?, LastAccessedDate = ? WHERE Id = ?

--not sure what this operation is for, but at this point in time NO GROUP EXISTs for this project ID
SELECT … FROM ProjectGroups groups0_ WHERE groups0_.ProjectId=?

--not sure what this is for either?
UPDATE Projects SET CreatedDate = ?, ModifiedDate = ?, LogoUrl = ?, LogoFilename = ?, Client = ?, Name = ?, Description = ?, LastAccessedDate = ? WHERE Id = ?

-- I've no idea why this is an UPDATE instead of an INSERT, but it will certainly update 0 rows instead of X, because no groups exist 
UPDATE ProjectGroups SET CreatedDate = ?, ModifiedDate = ?, DeletedDate = ?, Name = ?, ProjectId = ? WHERE Id = ?
Exception thrown: 'NHibernate.StaleStateException' in NHibernate.dll
Batch update returned unexpected row count from update; actual row count: 0; expected: 3
[ UPDATE ProjectGroups SET CreatedDate = @p0, ModifiedDate = @p1, DeletedDate = @p2, Name = @p3, ProjectId = @p4 WHERE Id = @p5 ]

Так почему же nHibernate решил, что его локальная сущность уже сохранена и, следовательно, доступна для UPDATE?Сгенерированный SQL должен быть вставкой, но я не уверен, как он управляет синхронизацией между локальным кешем и БД, чтобы узнать, существуют ли уже сущности или нет

Немного озадачен, что это работало в NH 2.x, но после обновления до последней версии (5.x) это исключение стало появляться.

1 Ответ

2 голосов
/ 30 мая 2019

Немного озадачен тем, что это работало в NH 2.x,

Обработка unsaved-value действительно изменилась в 5.2 с этим запросом на получение .Если я правильно понимаю, этот PR исправил некоторые случаи, когда приписанное unsaved-value отображение игнорировалось для назначенных идентификаторов.

Так что, похоже, у вас неправильное отображение unsaved-value для ваших сущностей с назначенным идентификатором.Из приведенных данных неясно, как вы ожидаете, что NHibernate определит, является ли сущность временной.С вашим отображением, если Id не равно Guid.Empty NHibernate будет запускать оператор UPDATE для всех каскадных объектов, и кажется, что вы видите именно такое поведение.Если вы хотите, чтобы он проверял базу данных, когда сущность отсутствует в сеансе - вместо этого установите "undefined":

Id(x => x.Id).GeneratedBy.GuidComb().UnsavedValue("undefined");

Если вы хотите, чтобы она всегда сохраняла сущность - установите ее на "any".

Чтение spec с пояснениями для всех других возможных значений.Также проверьте этот похожий выпуск .

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