我通过过程调用映射了带有自定义sql(插入,删除,更新)的类。但是,我注意到当我的插入过程无法引发异常时,来自NHibernate的GenericAdoException
没有从过程中引发我的消息。
但是,删除和更新过程中所有引发的异常都很好,只有插入过程没有捕获它的异常消息。
当我们使用“本机”生成器将id与自定义sql结合使用时,这是NHibernate 3.2.4的限制还是错误?
我正在寻找从这些过程中获取一些参数的方法,比如每个事件的时间戳(插入,删除和更新),时间戳在过程中生成。
EDIT:OUT PARAMs - 我在属性映射选项中找到了“generated”选项,我们可以要求NHibernate从程序中获取参数。这意味着这些属性具有genarated值。所以我尝试使用generated =“always”并适用于插入,更新和删除操作。示例:<property name="MyProp" generated="always"/>
答案 0 :(得分:0)
我发现当您使用ExecuteReader()
运行这些存储过程时,sql server驱动程序不会将存储过程引发的消息放入SqlException中。另一方面,NHibernate使用ExecuteReader()
执行自定义sql-insert(我对其源代码进行了重新编写),我认为在使用本机映射时获取密钥是正确和必要的(或者身份),我的情况。
session.save()
时,如何让它们穿过NHibernate核心并被我们的应用程序接收?
尽管我们有权访问会话,因此对于连接(SqlConnection),消息已经丢失,因为它们仅在事件发生之前被分配给事件SqlConnection.InfoMessage
的代理接收。
为了解决这个问题,我尝试了两种方法:
DriverConnectionProvider.GetConnection()
内注册委托的方法,这个委托会将消息存储在线程上下文中,并将其与连接相关联,因此这些消息可以在以后获取。IDbConnection
和IDbCommand
包裹SqlConnection
和SqlCommand
(但我认为NHibernate有一个错误,因为在有些地方它引用了DbConnection而不是IDbConnection - 就像在ManagedProviderConnectionHelper中一样,所以我不得不从DbConnection和DbCommand扩展而来。 在我的CustomSqlConnection中,我注册了委托并存储了这些消息供以后使用。 这很有效!作为独立驱动程序(ADO)作为NHibernate驱动程序工作。
这个想法是:
public class CustomSqlConnection : DbConnection, IDbConnection {
private SqlConnection con;
private StringBuilder str = new StringBuilder(0);
public CustomSqlConnection() {
con = new SqlConnection();
con.InfoMessage += OnInfoMessage;
}
private void OnInfoMessage(object sender, SqlInfoMessageEventArgs e) {
if (str.Length > 0) {
str.Append("\n");
}
str.Append(e.Message);
}
public string FetchMessage() {
string msg = Message;
str.Clear();
return msg;
}
...
...
}
编辑:艰难的一步是从DdConnection和Dbcommand实现所有操作,修复对sql实例的调用(查看上面的字段con
),所以:
...
public override void Open() {
con.Open();
}
...