2

RavenDBを使用するとIDocumentSession、アプリの起動時に作成し(アプリが閉じられるまで閉じない)、次のようにして楽観的同時実行性を使用できます。

public class GenericData : DataAccessLayerBase, IGenericData
{
    public void Save<T>(T objectToSave)
    {
        Guid eTag = (Guid)Session.Advanced.GetEtagFor(objectToSave);
        Session.Store(objectToSave, eTag);
        Session.SaveChanges();
    }
}

別のユーザーがそのオブジェクトを変更した場合、保存は正しく失敗します。

しかし、アプリの存続期間中に1つのセッションを使用する場合、私ができないことは、アプリの他のインスタンス(たとえば、5キュービクル離れたジョー)によってドキュメントに加えられた変更を確認することです。これを行うと、ジョーの変更が表示されません。

public class CustomVariableGroupData : DataAccessLayerBase, ICustomVariableGroupData
{
    public IEnumerable<CustomVariableGroup> GetAll()
    {
        return Session.Query<CustomVariableGroup>();
    }
}

注:これも試しましたが、Joeの変更も表示されませんでした。

return Session.Query<CustomVariableGroup>().Customize(x => x.WaitForNonStaleResults());

さて、IDocumentSession逆に、データベースにアクセスするすべてのメソッド内に作成すると、逆の問題が発生します。新しいセッションがあるので、ジョーの変化を見ることができます。Buuuuuuut...それから私は楽観的同時実行性を失います。保存する前に新しいセッションを作成すると、この行は空のGUIDを生成するため、失敗します。

Guid eTag = (Guid)Session.Advanced.GetEtagFor(objectToSave);

私は何が欠けていますか?各メソッド内でもアプリレベルでもセッションを作成するべきではない場合、正しいスコープは何ですか?Session.Query()を実行するときに、楽観的同時実行性他のユーザーの変更を確認する機能の利点をどのように得ることができますか?

4

3 に答える 3

2

同じセッションを使用しているため、変更は表示されません。詳細については、他の人の返信を参照してください

于 2011-12-30T09:22:06.627 に答える
2

免責事項:これは長期的なアプローチではないことを私は知っているので、ここでは受け入れられる答えにはなりません。ただし、今は何かを機能させる必要があり、後でリファクタリングできます。私はまた、何人かの人々がこのアプローチにうんざりすることを知っています、笑、しかしそうです。動作しているようです。すべてのクエリ(新しいセッション)で新しいデータを取得し、楽観的同時実行性も機能します。

肝心なのは、データアクセス方法ごとに1つのセッションに戻ったことです。そして、データアクセスメソッドが何らかのタイプのget / load / queryを実行するときはいつでも、eTagを静的ディクショナリに保存します。

public IEnumerable<CustomVariableGroup> GetAll()
{
    using (IDocumentSession session = Database.OpenSession())
    {
        IEnumerable<CustomVariableGroup> groups = session.Query<CustomVariableGroup>();
        CacheEtags(groups, session);
        return groups;
    }
}

次に、データを保存するときに、キャッシュからeTagを取得します。これにより、別のインスタンスがデータを変更した場合に同時実行例外が発生します。これは私が望んでいることです。

public void Save(EntityBase objectToSave)
{
    if (objectToSave == null) { throw new ArgumentNullException("objectToSave"); }

    Guid eTag = Guid.Empty;

    if (objectToSave.Id != null)
    {
        eTag = RetrieveEtagFromCache(objectToSave);
    }

    using (IDocumentSession session = Database.OpenSession())
    {
        session.Advanced.UseOptimisticConcurrency = true;
        session.Store(objectToSave, eTag);
        session.SaveChanges();
        CacheEtag(objectToSave, session);  // We have a new eTag after saving.
    }
}

長期的には絶対に正しい方法でやりたいと思っていますが、まだその方法がわかりません。

編集:より良い方法が見つかるまで、これを受け入れられた答えにします。

于 2011-12-30T18:53:27.907 に答える
1

ボブ、データを更新するたびに新しいセッションを開いてみませんか?

リクエストごとに新しいセッションを開くには多くのトレードオフがあり、楽観的同時実行制御(独自のシングルトンディクショナリ内でタグを管理する)に対するソリューションは、そのように使用することを意図したものではないことを示しています。

WPFアプリケーションがあるとおっしゃいました。了解しました。起動時に新しいセッションを開きます。必要なものをロードしてクエリを実行しますが、データを更新するまでセッションを閉じないでください(たとえば、注文のリスト、顧客、わかりません...)。次に、更新する場合(ユーザーがボタンをクリックした後、タイマーイベントが発生するなど)、セッションを破棄して新しいセッションを開きます。それはあなたのために働きますか?

于 2012-01-04T01:29:24.077 に答える