众所周知,在.Net中引入模式TransactionScope
时会被遗忘async
await
.如果我们试图await
在事务范围内使用某些调用,它们就会被破坏.
现在,由于范围构造函数选项,这已得到修复.
但它看起来仍然有一个缺失的部分,至少我无法找到如何以简单的"事务范围"方式做到这一点:如何等待提交或回滚范围?
提交和回滚也是IO操作,它们应该是等待的.但由于它们发生在范围处理上,我们将不得不等待处置.这看起来并不可行(using
模式也不实用).
我也看了一下System.Transactions.Transaction
界面:那里也没有等待的方法.
我知道提交和回滚几乎只是向数据库发送一个标志,所以它应该很快.但是对于分布式事务,这可能会更快.无论如何,这仍然是一些阻止IO.
关于分布式案例,请记住这可能会触发两阶段提交.在某些情况下,在第一阶段(准备)期间会招募额外的耐用资源.然后通常意味着针对那些最近登记的资源发布了一些额外的查询.提交期间发生的所有事情.
那么有没有办法等待交易范围?或者System.Transactions.Transaction
相反?
注意:我不认为这是" 可以在异步中提交/回滚SqlTransaction吗? " 的副本.SqlTransaction
比系统事务更有限.它们只能处理SQL-Server,并且永远不会分发.其他一些事务确实有异步方法,例如Npgsql.现在,对于事务范围/系统事务具有异步方法,DbTransaction
可能需要具有异步方法.(我不知道系统事务的内部,但它可能使用这个ADO.NET契约.我们将连接到系统事务的方式让我觉得它不会使用它.)
我有一个相当简单的条件查询来获取子集合,如下所示:
var order = Session.CreateCriteria<Order>()
.Add(Restrictions.Eq("Id", id))
.SetFetchMode("Customer", FetchMode.Eager)
.SetFetchMode("Products", FetchMode.Eager)
.SetFetchMode("Products.Category", FetchMode.Eager)
.SetCacheable(true)
.UniqueResult<Order>();
Run Code Online (Sandbox Code Playgroud)
使用NH Prof,我已经验证这只使用冷缓存只进行一次数据库往返(如预期); 但是,在连续执行时,它仅从Order
缓存中检索,然后使用SELECT(N + 1)为图中的每个子实体命中数据库,如下所示:
Cached query: SELECT ... FROM Order this_ left outer join Customer customer2 [...]
SELECT ... FROM Customer WHERE Id = 123;
SELECT ... FROM Products WHERE Id = 500;
SELECT ... FROM Products WHERE Id = 501;
...
SELECT ... FROM Categories WHERE Id = 3;
Run Code Online (Sandbox Code Playgroud)
等等等等.显然,它不缓存整个查询或图形,只缓存根实体.第一个"缓存查询"行实际上具有join
它应该具有的所有条件 - 它肯定正确地缓存了查询本身,显然不是实体.
我已经尝试过使用SysCache,SysCache2甚至是HashTable缓存提供程序,而且我似乎总是得到同样的行为(NH版本3.2.0). …
我正在尝试让NHibernate使用集合的许多方面来管理双向关联以建立零对一关系.
父类和地图:
public class Parent
{
private ICollection<Child> children;
public Parent()
{
this.children = new HashedSet<Child>();
}
public virtual Guid Id { get; protected internal set; }
public virtual Child Child
{
get { return children.FirstOrDefault(); }
set
{
{
this.children.Clear();
if (value != null)
{
this.children.Add(value);
}
}
}
}
}
public class ParentMap : ClassMap<Parent>
{
public ParentMap()
{
this.Id(x => x.Id)
.GeneratedBy.GuidComb();
this.HasMany<Child>(Reveal.Member<Parent>("children"))
.Access.Field()
.Cascade.All()
.Not.Inverse()
.AsSet();
}
}
Run Code Online (Sandbox Code Playgroud)
儿童班和地图:
public class Child
{
public virtual Guid …
Run Code Online (Sandbox Code Playgroud) 目标:
创建一个父子关系,以便修改父项的子项列表将传播给所有子项,并让NHibernate完成繁重的任务.父子关系将Has-Many
在自引用表上.
问题:
任何删除父(根)对象的尝试都会导致异常,而不是删除子对象的预期行为.
我正在使用的东西的版本:
Microsoft SQL Server Management Studio版本10.0.4064.0
FluentNHibernate版本1.3
NHibernate版本3.2.0.4
下面是我用来复制此行为的当前类对象和表结构的集合.
// Entity
class Task
{
ID { get; set; }
public virtual IList<Task> Children { get; set; }
public virtual byte[] Version { get; protected set; }
public virtual bool IsNew() { return ID <= 0; }
public Task()
{
this.Children = new System.Collections.Generic.List<Task>();
}
// Other properties excluded for brevity
}
Run Code Online (Sandbox Code Playgroud)
// Map
class TaskMap : ClassMap<Task>
{
TaskMap()
{
Table("Task");
Id(x => x.ID, …
Run Code Online (Sandbox Code Playgroud) 我有以下代码(为了讨论而简化).我不明白的是为什么session.Transaction
属性在回滚后返回不同的事务.
例如,这意味着该属性Session.Transaction.WasRolledBack
几乎没有帮助,除非我存储对第一个事务的引用并检查该事务的属性.
任何人都可以提供一些见解吗?
int transId = session.Transaction.GetHashCode();
using (var tx = session.BeginTransaction())
{
Assert.AreEqual(transId, tx.GetHashCode());
tx.Rollback();
Assert.AreEqual(transId, tx.GetHashCode());
Assert.AreEqual(transId, session.Transaction.GetHashCode()); // Fails
}
Run Code Online (Sandbox Code Playgroud)
更新:
David Walschots的回答非常有用且精确.另外,我在Nhibernate文档中找到了以下内容:
如果你回滚事务,你应该立即关闭并放弃当前会话,以确保NHibernate的内部状态是一致的."
我有这门课
public class Bill : EntityBase
{
public virtual decimal Value { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
在下面的映射中,我使用a中的过程填充'Value'的值 Formula()
public class MapBill : ClassMap<Bill>
{
public MapBill()
{
Table("cabrec");
Map(m => m.Value)
.Formula(
"(select t.VALOR_IND from ret_vlorind(1,1,cast('02/06/1993' as Date)) as t)")
.CustomType(typeof(decimal));
}
}
Run Code Online (Sandbox Code Playgroud)
但它在执行时返回错误:
{"Dynamic SQL Error\r\nSQL error code = -104\r\nToken unknown - line 1, column 279\r\n."}
Run Code Online (Sandbox Code Playgroud)
有没有办法在流利的nhibernate中使用程序?
据ODBC文档,ODBC支持SQL 2008+类型的喜欢datetime2
,date
,time
和datetimeoffset
。
但我无法将它们与 .NetSystem.Data.Odbc
连接和命令一起使用,但除外Date
。尽管我有“ODBC Driver 13 for SQL Server”及其“SQL Server Native Client 11.0”驱动程序,但它们看起来不受此 ODBC 客户端的支持:
尝试使用阅读器阅读Time
专栏会
产生:System.Data.Odbc
GetValue
System.ArgumentException : Unknown SQL type - SS_TIME_EX.
at System.Data.Odbc.TypeMap.FromSqlType(SQL_TYPE sqltype)
at System.Data.Odbc.OdbcDataReader.GetSqlType(Int32 i)
at System.Data.Odbc.OdbcDataReader.GetValue(Int32 i)
Run Code Online (Sandbox Code Playgroud)尝试用阅读器阅读一Time
列会减少几秒钟的时间。System.Data.Odbc
GetTime
Time
参数上设置一个OdbcCommand
减少它的小数秒。尝试DateTime2
在OdbcCommand
产量上设置参数:
System.ArgumentException : No mapping exists from DbType DateTime2 to a known …
Run Code Online (Sandbox Code Playgroud)如何通过字符串属性的长度限制查询?例如。就像是:
NHSession.QueryOver<Customer>()
.Where(p => p.RegistryCode.Length == 8)
Run Code Online (Sandbox Code Playgroud) 在 Visual Studio 2019 中,当我更改本地“查找和替换”的选项(区分大小写、整个单词或不是)时,这些设置将被保留并重用于所有其他文件。
在 Visual Studio 2022 中,这似乎仅适用于全局“在文件中查找”对话框,而不再适用于文件的本地“查找覆盖”。相反,本地“查找”设置似乎是在每个文件的基础上保留的,这意味着我必须为尚未完成本地查找的每个文件更改它们。
当我使用“不寻常”选项进行搜索时,我必须在该特定文件中的下一次搜索时更改它们,而不是在任何地方进行的下一次搜索时更改它们。这可能会在稍后的时间发生,以至于我将不再关注这些设置,而不记得我在该文件中之前的搜索中使用了特殊的设置。
我觉得这很烦人。我还没有找到将其恢复为 2019 年行为的选项。有办法恢复吗?
我所说的“本地查找和替换”是文件编辑器中的这一层:
设置是覆盖层底部的按钮和下拉列表。
我只想更新数据库中记录的一列。不是整个记录,而只是一列 (Stav)。我正在使用 NHibernate 并通过 DAO 访问。
Rezervace_dao rezervaceDao = new Rezervace_dao();
r.Stav = 1;
rezervaceDao.Update(r);
Run Code Online (Sandbox Code Playgroud)
上面的代码更新了整个记录,但这不是我想要的。
非常感谢。
nhibernate ×7
c# ×4
.net ×3
asp.net ×1
asp.net-mvc ×1
async-await ×1
firebird ×1
odbc ×1
orm ×1
queryover ×1
sql-server ×1
syscache2 ×1
transactions ×1