Wie kann NHibernate mitgeteilt werden, dass ein Trigger eine andere Tabelle aktualisiert?

8

Ich habe gerade einen TooManyRowsAffectedException während mit NHibernate arbeiten, und ich habe Abhilfen für gesehen durch eine andere batcher Injektion wie hier TooManyRowsAffcessedException mit verschlüsselten Triggern , oder indem die Trigger in der Datenbank so geändert werden, dass SET NOCOUNT ON verwendet wird (ich kann dieses nicht verwenden, da ich die Datenbank nicht ändern möchte ist sehr komplex mit mehr als hundert Tischen, die alle miteinander verwandt sind und ich möchte nicht damit herumhantieren, da andere Anwendungen es benutzen). Was ich nicht verstehe ist, warum diese Ausnahme passiert. Alles, was ich tue, ist, dass ich ein Sample-Objekt habe, das ein paar Werte hat, die ich überprüfe, und wenn die Werte mit bestimmten Kriterien übereinstimmen, setze ich die Sample.IsDone-Zeile auf 'Y' (in unserer Datenbank werden alle booleschen Werte durch a dargestellt char Y oder N). Der Code ist sehr einfach:

%Vor%

Der Flush-Anruf löst aus, ob ich ihn in die Schleife oder nach draußen lege. Gibt es etwas, was ich falsch mache, oder hängt es nur mit der Art zusammen, wie die Datenbank erstellt wird? Ich habe versucht, SaveOrUpdate () auf das Beispiel vor Flush (), aber es hat nichts geändert. Ich weiß, dass ich diese Ausnahme umgehen kann, aber ich würde lieber die Ursache des Problems verstehen.

Hinweis: In der Ausnahme sagt es mir, dass die tatsächliche Zeilenanzahl 2 und die erwartete 1 ist. Warum aktualisiert es 2 Zeilen, da ich nur 1 Zeile ändere?

Vielen Dank für Ihre Hilfe!

BEARBEITEN:

Ich konnte herausfinden, dass die Ursache dafür darin liegt, dass ein Trigger in der Datenbank eine Zeile in der Containertabelle aktualisiert (Container enthalten Samples), wenn das Beispiel aktualisiert wird. Gibt es eine Möglichkeit, NHibernate so zu konfigurieren, dass es diesen Trigger kennt und erwartet, dass die richtige Anzahl von Zeilen aktualisiert wird?

    
Carl 05.07.2011, 13:41
quelle

3 Antworten

5

Die einzige Arbeit, die ich gefunden habe, ist im folgenden Codeausschnitt mit Fluent NHibernate dargestellt. Es ist hässlich, da es schwer ist, SQL in Ihr Mapping zu codieren, aber es funktioniert. Die Check-Eigenschaft wird auf None festgelegt, sodass die Anzahl ignoriert wird. Ich weiß nicht, ob Sie dies mit geraden HBM-Dateien erreichen können, aber es gibt wahrscheinlich einen Weg. Es wäre großartig, wenn es eine Konfigurationsoption in NHibernate (oder Fluent NH) gäbe, um entweder die erwartete aktualisierte Zeilenanzahl zu setzen oder sie bei Bedarf zu ignorieren.

%Vor%

BEARBEITEN: Für diejenigen unglücklichen Leute, die Fluent NHibernate nicht kennen oder die schmerzhafte Erzeugung von HBM-Dateien von Hand lieben, hier ist die HBM-Datei für dieses Beispiel-Mapping:

%Vor%     
Sixto Saez 06.07.2011, 15:17
quelle
2

Überprüfen Sie mit einem Profiler die SQL, die ausgeführt wird. anjlab sql profiler hat immer den Trick für mich gemacht.

Danach überprüfen Sie, ob Sie Trigger auf diesem Tisch haben - vielleicht verursachen sie einige Probleme.

BEARBEITEN

Sie sollten Ihren Auslöser wie hier ändern: Ссылка

    
sirrocco 05.07.2011 13:52
quelle
1

Es gibt nichts, was Sie tun können, um NHibernate mitzuteilen, dass ein Auslöser eine andere Entität in der Datenbank aktualisiert hat, außer sie zu ignorieren, wie Sixto Saez in seiner Antwort zeigt. Sie können EventListeners jedoch verwenden, um die Triggeraktion im Code auszuführen. Oder setzen Sie SET NOCOUNT am Anfang des Triggers und SET NOCOUNT am Ende, wenn das Update für den Rest Ihrer Transaktion keine Rolle spielt.

    
Peter 06.07.2011 21:39
quelle

Tags und Links