2013-05-20 72 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 
}