I'm using this code (simplified) to test some Exception and Error Handling:
我正在使用此代码(简化)来测试一些异常和错误处理:
// All the objects in the collection already exist in the database
// so NHibernate should throw an Exception because of a PK constraint
// violation
foreach (var existingEntity in existingEntities)
{
// Implementation calls Session.CreateTransaction(),
// but the interface returns System.Data.IDbTransaction.
// This assembly has no references to NHibernate.
using (var transaction = repo.CreateTransaction())
{
try
{
// Executes a simple insert
repo.SaveComposite(existingEntity);
transaction.Commit();
}
catch (Exception e)
{
transaction.Rollback();
// Only record the inner-most message
var innerException = e;
while (innerException.InnerException != null)
innerException = innerException.InnerException;
Errors.Add(new Error(ErrorCode.ExceptionOccurred, innerException.Message));
}
}
}
The problem is that each consecutive Exception contains the error text of the previous Exception.
问题是每个连续的Exception都包含前一个Exception的错误文本。
eg. When trying to insert 3 entities with existing IDs 1, 2 and 3, these are the InnerException messages that are generated:
例如。尝试插入具有现有ID 1,2和3的3个实体时,这些是生成的InnerException消息:
Item with ID 1:
ID为1的项目:
"Violation of PRIMARY KEY constraint 'PK_Example'. Cannot insert duplicate key in object 'dbo.Example'. The duplicate key value is (1).\r\nThe statement has been terminated."
“违反PRIMARY KEY约束'PK_Example'。无法在对象'dbo.Example'中插入重复键。重复键值为(1)。\ r \ n语句已终止。”
Item with ID 2:
ID为2的项目:
"Violation of PRIMARY KEY constraint 'PK_Example'. Cannot insert duplicate key in object 'dbo.Example'. The duplicate key value is (1).\r\nViolation of PRIMARY KEY constraint 'PK_Example'. Cannot insert duplicate key in object 'dbo.Example'. The duplicate key value is (2).\r\nThe statement has been terminated.\r\nThe statement has been terminated."
“违反PRIMARY KEY约束'PK_Example'。无法在对象'dbo.Example'中插入重复键。重复键值为(1)。\ r \ n修改PRIMARY KEY约束'PK_Example'。无法在对象中插入重复键' dbo.Example'。重复键值为(2)。\ r \ n语句已终止。\ r \ n语句已终止。“
Item with ID 3:
ID为3的项目:
"Violation of PRIMARY KEY constraint 'PK_Example'. Cannot insert duplicate key in object 'dbo.Example'. The duplicate key value is (1).\r\nViolation of PRIMARY KEY constraint 'PK_Example'. Cannot insert duplicate key in object 'dbo.Example'. The duplicate key value is (2).\r\nViolation of PRIMARY KEY constraint 'PK_Example'. Cannot insert duplicate key in object 'dbo.Example'. The duplicate key value is (3).\r\nThe statement has been terminated.\r\nThe statement has been terminated.\r\nThe statement has been terminated."
“违反PRIMARY KEY约束'PK_Example'。无法在对象'dbo.Example'中插入重复键。重复键值为(1)。\ r \ n修改PRIMARY KEY约束'PK_Example'。无法在对象中插入重复键' dbo.Example'。重复键值为(2)。\ r \ n修改PRIMARY KEY约束'PK_Example'。无法在对象'dbo.Example'中插入重复键。重复键值为(3)。\ r \ n该声明已被终止。\ r \ n声明已终止。\ r \ n该声明已终止。“
Is this a SQL Server or NHibernate problem? How can I force NHibernate to clear the previous error message?
这是SQL Server还是NHibernate的问题?如何强制NHibernate清除以前的错误消息?
[EDIT]: If I set the batch_size to 1 (it's currently using the default batch_size) then the same error message is repeated and nested for each iteration.
[编辑]:如果我将batch_size设置为1(它当前使用的是默认的batch_size),则会为每次迭代重复并嵌套相同的错误消息。
The problem also persists after calling Session.Clear().
调用Session.Clear()后问题也会持续存在。
1 个解决方案
#1
0
Normally when you encounter an exception you do not want to reuse your ISession. ISessions should be disposed of after an exception occurs.
通常,当您遇到异常时,您不希望重用ISession。在发生异常后应该处理ISessions。
I'll also mention that I'm not sure how the errors are duplicated exactly. You mention specific output but is that being outputted by the following statement?
我还要提到我不确定错误是如何重复的。你提到具体的输出,但是由以下声明输出?
Errors.Add(new Error(ErrorCode.ExceptionOccurred, innerException.Message));
If you are logging or outputting each error as it's being added to that "collection" you would get the output you are describing above. You would want to instead wait until the end of foreach loop to output anything you have added to Errors
. You may want to watch the sql being ran as you debug it to verify what I'm saying.
如果您正在记录或输出每个错误,因为它将被添加到该“集合”中,您将获得上面描述的输出。您可能希望等到foreach循环结束时输出您添加到错误的任何内容。您可能希望在调试时看到正在运行的sql以验证我在说什么。
I'll also mention that if you are trying to save entities that may or may not exist you may want to use ISession.Merge instead of what you are currently using.
我还要提到,如果您尝试保存可能存在或可能不存在的实体,您可能希望使用ISession.Merge而不是您当前使用的实体。
From the NHibernate documentation:
从NHibernate文档:
This method copies the state of the given object onto the persistent object with the same identifier. If there is no persistent instance currently associated with the session, it will be loaded. The method returns the persistent instance. If the given instance is unsaved or does not exist in the database, NHibernate will save it and return it as a newly persistent instance. Otherwise, the given instance does not become associated with the session. In most applications with detached objects, you need both methods, SaveOrUpdate() and Merge().
此方法将给定对象的状态复制到具有相同标识符的持久对象上。如果当前没有与会话关联的持久性实例,则将加载该实例。该方法返回持久化实例。如果给定的实例未保存或数据库中不存在,NHibernate将保存它并将其作为新的持久化实例返回。否则,给定实例不会与会话关联。在大多数具有分离对象的应用程序中,您需要两种方法,SaveOrUpdate()和Merge()。
#1
0
Normally when you encounter an exception you do not want to reuse your ISession. ISessions should be disposed of after an exception occurs.
通常,当您遇到异常时,您不希望重用ISession。在发生异常后应该处理ISessions。
I'll also mention that I'm not sure how the errors are duplicated exactly. You mention specific output but is that being outputted by the following statement?
我还要提到我不确定错误是如何重复的。你提到具体的输出,但是由以下声明输出?
Errors.Add(new Error(ErrorCode.ExceptionOccurred, innerException.Message));
If you are logging or outputting each error as it's being added to that "collection" you would get the output you are describing above. You would want to instead wait until the end of foreach loop to output anything you have added to Errors
. You may want to watch the sql being ran as you debug it to verify what I'm saying.
如果您正在记录或输出每个错误,因为它将被添加到该“集合”中,您将获得上面描述的输出。您可能希望等到foreach循环结束时输出您添加到错误的任何内容。您可能希望在调试时看到正在运行的sql以验证我在说什么。
I'll also mention that if you are trying to save entities that may or may not exist you may want to use ISession.Merge instead of what you are currently using.
我还要提到,如果您尝试保存可能存在或可能不存在的实体,您可能希望使用ISession.Merge而不是您当前使用的实体。
From the NHibernate documentation:
从NHibernate文档:
This method copies the state of the given object onto the persistent object with the same identifier. If there is no persistent instance currently associated with the session, it will be loaded. The method returns the persistent instance. If the given instance is unsaved or does not exist in the database, NHibernate will save it and return it as a newly persistent instance. Otherwise, the given instance does not become associated with the session. In most applications with detached objects, you need both methods, SaveOrUpdate() and Merge().
此方法将给定对象的状态复制到具有相同标识符的持久对象上。如果当前没有与会话关联的持久性实例,则将加载该实例。该方法返回持久化实例。如果给定的实例未保存或数据库中不存在,NHibernate将保存它并将其作为新的持久化实例返回。否则,给定实例不会与会话关联。在大多数具有分离对象的应用程序中,您需要两种方法,SaveOrUpdate()和Merge()。