3 votes

RavenDB - Un client ne peut pas voir les changements d'un autre client

Je lance deux instances de mon application. Dans une instance, je sauvegarde une de mes entités. Lorsque je vérifie le RavenDB (http://localhost:8080/raven), je peux voir le changement. Ensuite, dans mon autre client, je fais ceci (ci-dessous), mais je ne vois pas les changements de l'autre application. Que dois-je faire pour obtenir les données les plus récentes dans la base de données ?

public IEnumerable<CustomVariableGroup> GetAll()
{
    return Session
        .Query<CustomVariableGroup>()
        .Customize(x => x.WaitForNonStaleResults());
}

Edit : Le code ci-dessus fonctionne si j'essaie d'effectuer une modification et que j'obtiens une exception de concurrence. Après cela, lorsque j'appelle le rafraîchissement (qui invoque le code ci-dessus), cela fonctionne.

Voici le code qui effectue la sauvegarde :

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

Et voici la classe qui contient la base de données et la session :

public abstract class DataAccessLayerBase
{
    /// <summary>
    /// Gets the database.
    /// </summary>
    protected static DocumentStore Database { get; private set; }

    /// <summary>
    /// Gets the session.
    /// </summary>
    protected static IDocumentSession Session { get; private set; }

    static DataAccessLayerBase()
    {
        if (Database != null) { return; }

        Database = GetDatabase();
        Session = GetSession();
    }        

    private static DocumentStore GetDatabase()
    {
        string databaseUrl = ConfigurationManager.AppSettings["databaseUrl"];            

        DocumentStore documentStore = new DocumentStore();

        try
        {
            //documentStore.ConnectionStringName = "RavenDb";  // See app.config for why this is commented.
            documentStore.Url = databaseUrl;
            documentStore.Initialize();
        }
        catch
        {
            documentStore.Dispose();
            throw;
        }

        return documentStore;
    }

    private static IDocumentSession GetSession()
    {
        IDocumentSession session = Database.OpenSession();

        session.Advanced.UseOptimisticConcurrency = true;

        return session;
    }
}

4voto

Daniel Lang Points 4968

En l'absence d'informations plus détaillées et de code, je ne peux que deviner...

Veillez à appeler .SaveChanges() sur votre session. Sans spécifier explicitement une ITransaction, votre IDocumentSession sera isolée et transactionnelle entre son ouverture et l'appel à la fonction .SaveChanges . Soit toutes les opérations réussissent, soit aucune. Mais si vous ne l'appelez pas, toutes vos opérations précédentes de .Store seront perdus.

Si je me suis trompé, veuillez fournir plus de détails sur votre code.

EDIT : Deuxième réponse (après complément d'information) :

Votre problème est lié à la façon dont RavenDB met en cache le côté client. RavenDB met en cache par défaut chaque requête GET pendant toute la durée d'une session de document. Les requêtes simples sont juste des requêtes GET (et non, cela n'a rien à voir avec le fait que votre index soit dynamique ou défini manuellement en amont) et elles seront donc mises en cache. La solution dans votre application est de disposer de la session et d'en ouvrir une nouvelle.

Je vous suggère de repenser le cycle de vie de votre session. Il semble que vos sessions durent trop longtemps, sinon la concurrence ne serait pas un problème. Si vous construisez une application web, je vous recommande d'ouvrir et de fermer la session au début et à la fin de votre requête. Jetez un coup d'œil à RaccoonBlog pour voir une implémentation élégante.

2voto

frontsideair Points 221

Bob, Il semble que vous n'ayez qu'une seule session dans l'application, ce qui n'est pas correct. L'article suivant parle de NHibernate, mais les parties relatives à la gestion des sessions s'appliquent également à RavenDB :

http://archive.msdn.microsoft.com/mag200912NHibernate

Ce code n'a pas de sens :

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

Il s'agit en fait d'un "no op", mais qui a l'air important. Vous semblez essayer de travailler avec un modèle dans lequel vous devez gérer manuellement toutes les sauvegardes, ne faites pas cela. Vous n'avez besoin de gérer les choses vous-même que lorsque vous créez un nouvel élément, c'est tout.

En ce qui concerne la raison pour laquelle vous rencontrez ce problème, voici un exemple :

var session = documentStore.OpenSession();
var post1 = session.Load<Post>(1);
// change the post by another client
post2 = session.Load<Post>(1); // will NOT go to the server, will give the same instance as post1

Assert.ReferenceEquals(post1,post2);

Les sessions sont de courte durée et sont généralement utilisées dans le cadre d'un seul formulaire ou d'une seule demande.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X