2011-05-12 8 views
7

Saqué un ejemplo del this MSDN page y lo he usado casi textualmente. Cuando se ejecuta, el código se compila correctamente, pero changeCount aumenta infinitamente si ha habido o no un cambio en los datos devueltos. Cuando se produce un cambio realmente dataGridView1 refleja el cambio correctamente. ¿Por qué mi SqlDependency parece que está disparando en un bucle a pesar de que aparentemente no ha habido cambios?El uso de SqlDependency da como resultado actualizaciones constantes

Aquí está la fuente:

#region Using directives 
using System; 
using System.Collections; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Data.SqlClient; 
using System.Drawing; 
using System.Linq; 
using System.Runtime.InteropServices; 
using System.Security.Permissions; 
using System.Text; 
using System.Windows.Forms; 
#endregion 

namespace PreAllocation_Check 
{ 
    public partial class Form1 : Form 
    { 
     int   changeCount = 0; 
     const string tableName = "MoxyPosition"; 
     const string statusMessage = "Last: {0} - {1} changes."; 
     DataSet  dataToWatch = null; 
     SqlConnection MoxyConn = null; 
     SqlCommand SQLComm = null; 

     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void Form1_Load(object sender, EventArgs e) 
     { 
      if (CanRequestNotifications()) 
      { 
       SqlDependency.Start(GetConnectionString()); 

       if (MoxyConn == null) 
        MoxyConn = new SqlConnection(GetConnectionString()); 

       if (SQLComm == null) 
       { 
        SQLComm = new SqlCommand(GetSQL(), MoxyConn); 

        SqlParameter prm = new SqlParameter("@Quantity", SqlDbType.Int); 
        prm.Direction = ParameterDirection.Input; 
        prm.DbType = DbType.Int32; 
        prm.Value = 100; 
        SQLComm.Parameters.Add(prm); 
       } 

       if (dataToWatch == null) 
        dataToWatch = new DataSet(); 

       GetData(); 
      } 
     } 

     private void Form1_FormClosed(object sender, FormClosedEventArgs e) 
     { 
      SqlDependency.Stop(GetConnectionString()); 
      if (MoxyConn != null) 
       MoxyConn.Close(); 
     } 

     private bool CanRequestNotifications() 
     { 
      try 
      { 
       SqlClientPermission SQLPerm = new SqlClientPermission(PermissionState.Unrestricted); 
       SQLPerm.Demand(); 
       return true; 
      } 
      catch 
      { 
       return false; 
      } 
     } 

     private string GetConnectionString() 
     { 
      return "server=***;database=***;user id=***;password=***"; 
     } 

     private void GetData() 
     { 
      dataToWatch.Clear(); 
      SQLComm.Notification = null; 
      SqlDependency SQLDep = new SqlDependency(SQLComm); 
      SQLDep.OnChange += new OnChangeEventHandler(SQLDep_OnChange); 

      using (SqlDataAdapter adapter = new SqlDataAdapter(SQLComm)) 
      { 
       adapter.Fill(dataToWatch, tableName); 
       dataGridView1.DataSource = dataToWatch; 
       dataGridView1.DataMember = tableName; 
      } 
     } 

     private string GetSQL() 
     { 
      return "SELECT PortID, CONVERT(money, SUM(PreAllocPos), 1) AS PreAllocation, CONVERT(money, SUM(AllocPos), 1) AS Allocation, CONVERT(money, SUM(PreAllocPos) - SUM(AllocPos), 1) AS PreLessAlloc " + 
        "FROM MoxyPosition " + 
        "WHERE CONVERT(money, PreAllocPos, 1) <> CONVERT(money, AllocPos, 1) " + 
        "GROUP BY PortID " + 
        "ORDER BY PortID ASC;"; 
     } 

     void SQLDep_OnChange(object sender, SqlNotificationEventArgs e) 
     { 
      ISynchronizeInvoke i = (ISynchronizeInvoke)this; 

      if (i.InvokeRequired) 
      { 
       OnChangeEventHandler tempDelegate = new OnChangeEventHandler(SQLDep_OnChange); 
       object[] args = { sender, e }; 
       i.BeginInvoke(tempDelegate, args); 
       return; 
      } 

      SqlDependency SQLDep = (SqlDependency)sender; 
      SQLDep.OnChange -= SQLDep_OnChange; 

      changeCount++; 
      DateTime LastRefresh = System.DateTime.Now; 
      label1.Text = String.Format(statusMessage, LastRefresh.TimeOfDay, changeCount); 

      GetData(); 
     } 
    } 
} 

Editar: Vale la pena señalar que la base de datos que desea ejecutar esto en contra de la actualidad no han permitido que el Service Broker, y así poner a prueba mi código I copia de seguridad de mi meta la base de datos y la restauró con un nuevo nombre, luego ejecutó ALTER DATABASE my_db_name SET ENABLE_BROKER en su contra. Todas mis pruebas han estado en esta base de datos alternativa, lo que significa que soy el único usuario en ella.

Respuesta

0

que no tienen una respuesta para esto, pero se rompió al menos una de las reglas aquí: http://msdn.microsoft.com/en-us/library/aewzkxxh.aspx

cuando usted no pudo utilizar los nombres de tabla de dos partes. Cambie MoxyPosition a dbo.MoxyPosition y revise las reglas vinculadas anteriormente. Espero que ayude, pero algo me dice que algo más tiene la culpa aquí.

1

Tuve un problema similar. Resulta que al hacer SELECT * FROM dbo.MyTable estaba causando que la actualización se disparara constantemente. Cambiar a SELECT Id, Column1, Column2 FROM dbo.MyTable solucionó el problema.

Parece que no está usando * en su consulta, pero puede intentar simplificar su consulta para ver si todavía tiene el problema.

4

Esta es una pregunta anterior, pero el problema es que su consulta no cumple con los requisitos.

Respuesta corta:
complemento nombre de esquema de la tabla "FROM DBO.MoxyPosition " +

Respuesta larga:
se puede ver una list of requirements here, que son muy similares a los de la creación de una vista indizada. Cuando se registra una Dependencia de SQL, si no es válida, la notificación se activa inmediatamente y le informa que no es válida. Cuando lo piensas, esto tiene sentido, porque ¿cómo puede Visual Studio saber cuáles son los requisitos internos para SQL Engine?

Por lo tanto, en su función SQLDep_OnChange querrá consultar el razón por la que activó la dependencia. El motivo se encuentra en la variable e (información, fuente y tipo).Los detalles sobre el objeto de evento se pueden encontrar aquí:

Para su aviso específico caso, ¿cómo MS describes la propiedad Type:

Gets a value that indicates whether this notification is generated 
because of an actual change, OR BY THE SUBSCRIPTION. 
+0

Muchas gracias! Esta respuesta me liberó de buscar e intentar por ahora unos dos días. –

0

ver que tipo de SqlNotificationEventArgs está en su controlador (definido a continuación). Si ves que golpeó cientos de veces y el tipo es cada vez suscribirse a continuación, la instrucción SQL es incorrecta - consulte las guías en otras publicaciones

private void HandleOnChange(object sender, SqlNotificationEventArgs e) 
{ 
... 

var someType = e.Type; /*If it is Subscribe, not Change, then you may have your SQL statement wrong*/ 
... 
} 
Cuestiones relacionadas