2010-07-21 2 views
1

J'ai deux programmes C# qui partagent un seul fichier de base de données SQLite. Un programme (appelons-le Writer) écrit de nouvelles données dans la base de données. L'autre programme (Reader) le lit. Les deux programmes utilisent Fluent NHibernate et System.Data.SQLite pour accéder à la base de données.NHibernate peut-il détecter lorsqu'un autre programme a écrit de nouvelles données dans une base de données SQLite partagée?

Actuellement, je viens d'avoir un gros bouton Actualiser dans mon programme Reader, et l'utilisateur doit cliquer dessus pour obtenir toutes les nouvelles données qui ont été écrites dans la base de données depuis la dernière actualisation. Cela fonctionne, mais n'est guère élégant.

Existe-t-il un moyen pour que NHibernate déclenche un événement dans le programme Reader lorsque la base de données est mise à jour par Writer, afin que je puisse automatiquement présenter de nouvelles données à l'utilisateur? (J'ai regardé les documents NH pour Interceptors et événements, mais il n'était pas clair si ceux-ci feraient ce que je veux)

Ou, y at-il un bon moyen d'interroger pour les mises à jour en utilisant NH?

A défaut d'une solution NH, puis-je faire quelque chose de similaire avec System.Data.SQLite, ou via un autre mécanisme de niveau inférieur?

Répondre

1

Vous pouvez mettre un System.IO.FileWatcher sur le fichier partagé. Cela vous dira quand il a été mis à jour.

+0

Vous voulez dire System.IO.FileSystemWatcher, n'est-ce pas? Merci pour la suggestion - l'exemple dans l'aide de .Net semble simple. Le seul inconvénient est que c'est un peu dépendant de DB, comme le mentionne zoidbeck. –

1

Je pense qu'un Interceptor ou Event du côté de l'écrivain serait la bonne solution pour cela. Dans notre projet actuel, nous avons fait quelque chose de similaire et cela fonctionne très bien. En utilisant cette approche, vous garderiez la possibilité de changer la base de données ci-dessous ou mappage et pourrait élaborer votre événement de mise à jour d'un simple déclencheur 'TableUpdate' qui devrait être fait en quelques heures à un événement de mise à jour concret contenant toutes les données ont changé.

EDIT:

Tout d'abord je voudrais suivre non seulement la OnSave mais aussi AfterTransactionCompleted pour assurer la transaction est comitted. Cela vous permet également de collecter tous les objets du tx. La meilleure façon de le faire est PRÉPONDÉRANTS l'objet EmptyInterceptor comme ceci:

public class EntityInterceptor : EmptyInterceptor 
{ 
    private IList<object> entities = new List<object>(); 

    public override bool OnSave(object entity, object id, object[] state, string[] propertyNames, NHibernate.Type.IType[] types) 
    { 
     entities.Add(entity); 
     return base.OnSave(entity, id, state, propertyNames, types); 
    } 

    public override void AfterTransactionCompletion(ITransaction tx) 
    { 
     if (tx.WasCommitted) 
     { 
      Console.WriteLine("Data has been inserted. Notify the reader here."); 
     } 
     entities = new List<object>(); 
    } 
} 

L'approche la plus straigthforward pour la communication inter-processus OMI serait .net Remoting. Il y a plusieurs exemples de comment le faire. Un simple peut être trouvé here. Ou si vous voulez essayer WCF voir here. Ou chercher SO, beaucoup de bons exemples peuvent être trouvés ici.

+0

Pourriez-vous donner plus de détails? Je pense que je comprends comment je peux intercepter les événements OnSave dans mon programme Writer, mais que dois-je faire dans le gestionnaire d'événements? Et que dois-je faire du côté du lecteur? Pourriez-vous fournir des exemples de code ou me donner un bon exemple? –

+0

Merci pour l'édition - Je comprends votre approche maintenant. Et le lien WCF était très utile aussi! –

0

Voici quelques exemples de code qui utilise FileSystemWatcher, comme suggéré par John Rayner ...

 // Watches for writes to database file 
    private static FileSystemWatcher _dbFileWatcher; 

    /// <summary> 
    /// Set up an event handler that is called when SQLite database is written to. 
    /// </summary> 
    /// <param name="onChangedHandler"></param> 
    public static void SetupSqliteDatabaseWatcher(FileSystemEventHandler onChangedHandler) 
    { 
     // Create a new FileSystemWatcher and set its properties. 
     _dbFileWatcher = new FileSystemWatcher 
          { 
           Path = "<directory containing DB file>", 
           Filter = "<DB file>.db", 
           NotifyFilter = NotifyFilters.LastWrite 
          }; 

     // Add the event handler 
     _dbFileWatcher.Changed += onChangedHandler; 

     // Begin watching. 
     _dbFileWatcher.EnableRaisingEvents = true; 
    } 

    // Event handler 
    private static void OnDbWritten(object source, FileSystemEventArgs e) 
    { 
     Debug.Print("DB written"); 
    } 


    // Set up the event handler 
    SetupSqliteDatabaseWatcher(OnDbWritten); 
+0

Innovant, mais l'approche de l'auditeur ou de l'intercepteur serait probablement un meilleur choix. Vous pouvez filtrer par type d'entité (c'est-à-dire regarder certaines classes uniquement), il n'est pas lié à une base de données spécifique et je ne connais pas les internes de SQLite, mais un processus automatique comme réindexer peut entraîner une écriture dans le fichier aucune mise à jour n'a eu lieu. –

Questions connexes