繁体   English   中英

NHibernate IStatelessSession CreateQuery失败

[英]NHibernate IStatelessSession CreateQuery failure

当我们上周五发布时,我收到了一个错误,我没有被接受。 错误消息是:

could not execute update query[SQL: delete from dbo.MyTable where col1=? and col2=? and col3=? and col4=? and col5=?]

我的C#代码如下:

var hqlDelete = "DELETE MyTable m WHERE m.Col1 = :var_1 AND m.Col2 = :var_2 AND m.Col3= :var_3 AND m.Col4 = :var_4 AND m.Col5= :var_5";
var deletedEntities = session.CreateQuery(hqlDelete)
                             .SetString("var_1", variable1)
                             .SetString("var_2", variable2)
                             .SetString("var_3", variable3)
                             .SetString("var_4", variable4)
                             .SetString("var_5", variable5)
                             .ExecuteUpdate();
transaction.Commit();
session.Close();

现在,正如我所说,在接受测试时不会触发错误。 另外,当我使用生产数据库(开发人员所在地的代码)进行测试时,它也可以正常工作。

当我调用Web服务并向其发布“度量”时,将触发代码。 唯一的区别是,我在测试时调用该服务,而在生产时,另一家公司将度量值发送到Web服务。

我认为这可能与会话/事务的数量有关,但这并不能真正解释为什么变量显示为? 在错误消息中。

有任何想法吗? 我是否可以提供更多信息,以便您可以帮助我?

编辑:InnerExeption是

{"Transaction (Process ID 68) was deadlocked on lock | communication buffer resources with another process and has been chosen as the deadlock victim. Rerun the transaction."}

解决死锁可能很困难,尤其是在使用ORM时。 死锁通常是由于不同的进程(或线程)没有以相同的顺序获取数据库对象上的锁而导致彼此等待而发生的。

ORM不会给您太多控制锁的顺序。 您可以重新整理查询顺序,但这可能很乏味。 特别是在缓存导致其中一些无法访问数据库时。 而且,应该在使用同一数据库的任何其他应用程序上以相同的顺序进行操作。

您可能会检测到死锁错误,然后执行以下消息:重试整个过程。 使用NHibernate,这意味着放弃当前会话,然后重试整个工作单元。

如果您的数据库是SQL Server,则有一个默认设置会大大增加死锁的风险:禁用读取提交的快照模式 如果在数据库上将其禁用,则可以通过启用它来大大降低死锁风险。 此模式允许处于读取提交隔离级别的读取停止发出读取锁定。

您可以通过以下方式检查此设置

select snapshot_isolation_state_desc, is_read_committed_snapshot_on
    from sys.databases 
    where name = 'YourDbName'

您可以通过以下方式启用此设置

alter database YourDbName
    set allow_snapshot_isolation on

alter database YourDbName
    set read_committed_snapshot on

这要求目标数据库上没有正在运行的事务。 当然,这需要具有数据库管理员权限。

在我没有选择更改此设置的应用程序上,我不得不采用一种更古怪的方式:将NHibernate默认隔离模式( connection.isolation配置参数 )设置为ReadUncommitted 我的应用程序大多数情况下是只读的,我正在显式地提升必须读取然后写入数据的少数事务的隔离模式session.BeginTransaction(System.Data.IsolationLevel.ReadCommitted)例如,使用session.BeginTransaction(System.Data.IsolationLevel.ReadCommitted) )。

您还应该检查所有使用数据库的应用程序当前使用的隔离模式:其中某些使用的隔离级别是否比实际需要的隔离级别高? (如果可能,应避免使用RepeatableReadSerializable 。)这是一个耗时的过程,因为在研究每个用例以确定合适的最小隔离级别时,它需要对隔离级别有很好的了解。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM