0

在这里,我使用事务范围存储类型为 transactionSummary 的文档,如下所示

public class TransactionSummary
{
[JsonIgnore]
        public Guid? Etag { get; set; }
        public String Id { get; set; }
        public String TransactId { get; set; }
        public OpenOrClosed BalanceType { get; set; }
        public TransactStatus Status { get; set; }
        public String PayeeAccountNo { get; set; }
        public Decimal AmountPaid { get; set; }
}



using (var trans = new TransactionScope())
{
  using (IDocumentSession sess = GetConnection())
   {
     sess.Store(fldtrans);
     sess.SaveChanges();
   }
    trans.complete();
}

立即存储后,我需要检索它,所以我按以下方式进行操作

   using (IDocumentSession sess = GetConnection())
   {
     sess.Advanced.AllowNonAuthoritativeInformation = false;
     sess.Advanced.UseOptimisticConcurrency = true;
     transact = sess.Query<TransactionSummary>().Where(x => x.TransactId ==transactid).FirstOrDefault();                                                                 
     transact.Etag = sess.Advanced.GetEtagFor(transact);
   }

这里我得到一个异常如下 ex = {"Value cannot be null.\r\nParameter name: key"}StackTrace = "
at System.Collections.Generic.Dictionary 2.FindEntry(TKey key)\r\n at System.Collections.Generic.Dictionary2.TryGetValue(TKey key, TValue& value)\r \n 在 Raven.Client.Document.InMemoryDocumentSessionOperations.GetDocumentMetadata[T](T instance) in c...

我知道提交事务需要一定的时间,因此当立即读取文档时它会失败。但是我怎样才能克服这个问题,这样我就不会牺牲我的要求。

马特在这里,我在该事务范围内也做了很多其他工作,我刚刚向您展示了一瞥,以便您了解其中之一是我将 TransactionId 发布到队列中,并且我的后台服务获取 transactionId(不是文档Id) 并执行其他一些需要在事务后完成的过程。这里发生的是队列在事务在真实数据库中受到影响之前较早地获取 transactionId。

这是我的 Getconnection 代码供参考。

public class DataAccess : IDataAccess
    {
        static IDocumentStore _docStore ;
        public DataAccess()
        {

            _docStore = new DocumentStore { Url = "http://localhost:8081" };
            _docStore.Initialize();
            _docStore.Conventions.IdentityPartsSeparator = "-";  

        }

        #region IDataAccess Members

        public IDocumentSession GetConnection()
        {

            IDocumentSession sess = _docStore.OpenSession();
            _docStore.DatabaseCommands.EnsureDatabaseExists("MyDB");
            return sess=_docStore.OpenSession("MyDB");
        }
4

1 回答 1

5

根据您所展示的内容,无需显式定义事务范围。会话范围定义的工作单元周围已经存在隐式事务。唯一需要显式使用TransactionScope的情况是,如果您正在调用两个或多个具有不同会话的独立数据库 - 或调用 raven 和其他一些事务感知进程。

我不确定为什么要在存储后立即在新会话中查询。您肯定会遇到过时的索引问题需要处理。如果你真的必须这样做,你可能应该只通过它的Id.

也许您没有意识到这一点,但在您的第一个会话中Id调用后立即可用.Store()- 甚至在您保存更改之前。如果您想获取文档的 etag,您可以在第一个会话中调用.GetEtagFor()之后立即调用。.SaveChanges()实际上没有必要为这些目的创建另一个会话。

如果您还没有阅读过,您还应该阅读这篇关于乐观并发和 etag 问题的 RavenDB 知识库文章。我想你会发现那里解决了你的大部分问题。

最后一件事 - 请更新您的问题以显示您的GetConnection()方法的代码。如果不显示,很难判断您是否正在使用IDocumentSession并且正确。IDocumentStore谢谢。

于 2013-04-12T14:00:11.010 回答