您好,我正在为 ASP.NET Web 应用程序使用每次请求事务( View 中的 session )模式。我在应用程序中有几点要保存 NHibernate 托管实体,然后使用通用 sql 执行更多插入和更新。这些插入/更新取决于 NH 保存的实体将采用的 ID。
问题是生成的 ID 不存在于事务范围内。如果我强制刷新/提交,则 id 会保留,但如果插入/更新失败,我必须回滚,但刷新/提交的实体不会。目前我正在为这些案例做一个手动插入,但这是我想改变的。那么,有没有一种方法可以在 Save() 之后执行 SQL 语句(在已经打开的事务中)而不强制刷新/提交?
编辑:我添加了一个半伪代码示例,我得到了 4 个错误答案,所以我认为人们不理解(NHibernate 是如何工作的) 在开始请求时,我发出一个
nhsession.BeginTransaction()
然后在某个时候我会做
FooClass fc = new FooClass("value");
nhsession.Save(fc);
ITransaction trans = nhsession.Transaction;
SqlCommand sc = new SqlCommand("some insert/update query that depends on fc's id", (SqlConnection)nhsession.Connection);
sc.Parameters.Add("id", fc.Id); //NHibernate generates the id, note i'm using assigned/hi-lo so no round trip to the db takes place
transaction.Enlist(sc);
try {
sc.ExecuteNonQuery();
}
catch (SqlException ex){
transaction.RollBack();
nhsession.Close();
}
并在请求结束时发出 CommitTransaction()
和 nhsession.Close()
现在这绝对什么也做不了:FooClass (fc)
还没有刷新/提交到数据库。 NH 完成的 Save()
操作是内存中的那个点。这意味着 nhibernate 没有发出任何 sql 命令,这意味着我之后触发的 SqlCommand (sc)
将因为 ID 不存在而惨败。
如果我在 Save()
和 SqlCommand
之间执行刷新/提交,FooClass(fc)
_cannot_be_rolled_back_ 这很糟糕事物。
目前,为了实现这一点,我使用 SqlCommand
制作了 vanila sql insert,我想改变它。 (为什么?因为我不想制作原始插入,它们很容易因模式/模型更改而出错,我为此获得了 OR/M)
如何?我想通知 NHibernate 以某种方式执行 SqlCommand
以对应于 Save()
插入(见鬼,它可以执行它收集的所有 SqlCommand)但没有提交或冲洗!
目前我也在搜索 nhibernate 在刷新/提交保存的对象时生成的准备好的 sql 语句。也许我可以只获取该字符串并在事务中登记的我的 SqlCommand 中运行它。
最佳答案
也许我不明白,但你能不能这样...
using(var tx = session.BeginTransaction())
{
session.Save(entity);
session.Flush();
//perform non NH operations with entity.id
tx.Commit();
}//uncommitted transaction would be rolled back on dispose()
关于c# - 在没有刷新/提交的情况下强制执行查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2275050/