2013-05-20 101 views
0

我一直在尋找一段時間,但沒有找到任何真正的答案。我試圖構建一個使用SQL Server CE的可移植性應用程序,並且我需要在數據庫更新時觸發事件。無論如何要這樣做,就像使用SQL Server CE的通知服務一樣嗎?SQL Server CE通知服務

感謝

+0

由於的SQL Server CE真不是** **服務器(儘管名稱不同),但是在您的應用程序中是一個「嵌入式」數據庫,我恐怕沒有提供這些服務。您必須定期輪詢您的數據庫表以檢測變化,然後對發生的變化做出反應。 –

+0

前段時間,我實現了一個非常「輕量級」的輪詢機制,請告訴我您是否感興趣,我會盡力挖掘出來。 – ErikEJ

+0

嗨ErikEJ,這將是超級! –

回答

0

這是一類做輕量輪詢的開始,需要看錶有一個IDENTITY列:

using System; 
using System.Collections.Generic; 
using System.Text; 
using System.Data.SqlServerCe; 

/// <summary> 
/// Sql Compact query notification class 
/// </summary> 
public sealed class SqlCeDependency : IDisposable 
{ 
    private System.Timers.Timer timer = new System.Timers.Timer(); 

    private Int64 lastUsedIdentity = Int64.MinValue; 
    private Int64 currentIdentity = Int64.MinValue; 

    private SqlCeConnection conn; 

    private string tableToWatch; 

    /// <summary> 
    /// Occurs when the underlying table changes. 
    /// Initial support only for Inserts 
    /// </summary> 
    public event EventHandler OnChange; 

    /// <summary> 
    /// Initializes a new instance of the <see cref="SqlCeDependency"/> class. 
    /// </summary> 
    /// <param name="tableToWatch">The table to watch.</param> 
    /// <param name="connectionString">The connection string.</param> 
    public SqlCeDependency(string tableToWatch, string connectionString) 
    { 
     this.tableToWatch = tableToWatch; 
     StartTimer(20, connectionString); 
    } 

    /// <summary> 
    /// Initializes a new instance of the <see cref="SqlCeDependency"/> class. 
    /// </summary> 
    /// <param name="tableToWatch">The table to watch.</param> 
    /// <param name="connectionString">The SQL Compact connection string.</param> 
    /// <param name="interval">The interval in seconds.</param> 
    public SqlCeDependency(string tableToWatch, string connectionString, int interval) 
    { 
     this.tableToWatch = tableToWatch;    
     StartTimer(interval, connectionString); 
    } 

    private void CheckDependency(string tableToWatch) 
    { 
     using (SqlCeCommand cmd = conn.CreateCommand()) 
     { 
      cmd.CommandText = string.Format("SELECT AUTOINC_NEXT FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '{0}' AND AUTOINC_NEXT IS NOT NULL", tableToWatch); 

      if (conn.State != System.Data.ConnectionState.Open) 
      { 
       conn.Open(); 
      } 
      object obj = cmd.ExecuteScalar(); 
      if (obj == null) 
      { 
       throw new NotSupportedException("IDENTITY column is required on watched table"); 
      } 
      else 
      { 
       lastUsedIdentity = (Int64)obj; 
      } 
      if (currentIdentity == Int64.MinValue) 
      { 
       currentIdentity = lastUsedIdentity; 
      }     
     } 
    } 

    private void StartTimer(int interval, string connectionString) 
    { 
     timer.Interval = interval * 1000; 
     timer.AutoReset = true; 
     timer.Enabled = true; 
     timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed); 
     conn = new SqlCeConnection(connectionString); 
     conn.Open(); 
    } 

    void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) 
    { 
     CheckDependency(tableToWatch); 
     if (lastUsedIdentity != currentIdentity) 
     { 
      currentIdentity = lastUsedIdentity; 
      if (OnChange != null) 
      { 
       OnChange(this, EventArgs.Empty); 
      } 
     } 
    } 

    public bool HasChanges { get; set; } 


    #region IDisposable Members 

    public void Dispose() 
    { 
     if (conn != null) 
     { 
      conn.Dispose(); 
     } 
    } 

    #endregion 
}