2011-05-12 2 views
7

this MSDN page에서 예제를 가져 와서 그대로 사용했습니다. 코드를 실행하면 올바르게 컴파일되지만 changeCount은 실제로 반환 된 데이터가 변경되었는지 여부에 관계없이 끝없이 증가합니다. 실제로 의 변경 내용이 인 경우 dataGridView1에 변경 사항이 올바르게 반영됩니다. 내 SqlDependency이 변경되지 않은 것처럼 보이지만 반복적으로 실행되는 것처럼 보이는 이유는 무엇입니까?SqlDependency를 사용하면 지속적인 업데이트가 발생합니다.

#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(); 
     } 
    } 
} 

편집 : 여기

소스의 데이타베이스가 나는 현재 브로커 서비스가 활성화되지 않습니다이에 대한 실행하려는 것을 주목할 필요가, 그래서 내가 백업 내 코드를 테스트하기 위해 내 새 이름으로 복원 한 다음 ALTER DATABASE my_db_name SET ENABLE_BROKER을 실행했습니다. 내 테스트는 모두이 대체 데이터베이스에 있었고, 이는 내가 유일한 사용자임을 의미합니다.

답변

0

나는 이것에 대한 대답이 없어,하지만 당신은 여기에 규칙 중 적어도 하나를 깰 않은 : 당신은 두 부분으로 테이블 이름을 사용하는 데 실패 http://msdn.microsoft.com/en-us/library/aewzkxxh.aspx

. MoxyPosition을 dbo.MoxyPosition으로 변경하고 위에 링크 된 규칙을 검토하십시오. 도움이되기를 바랍니다. 그러나 뭔가 다른 말로는 나에게 잘못이 있다고합니다.

1

비슷한 문제가있었습니다. 업데이트가 지속적으로 발생하는 원인이 된 SELECT * FROM dbo.MyTable이 발생합니다. SELECT Id, Column1, Column2 FROM dbo.MyTable으로 변경하면 문제가 해결되었습니다.

쿼리에 *이 사용 된 것 같지 않지만 쿼리를 단순화하여 문제가 계속 발생하는지 확인해보십시오.

4

이 질문은 오래된 질문이지만 쿼리가 요구 사항을 충족하지 못하는 것입니다.

짧은 답변 : 테이블 "FROM DBO.MoxyPosition " +


추가 스키마 이름 긴 대답 :

당신은 인덱싱 된 뷰를 생성하는 것과 매우 유사됩니다 list of requirements here를 볼 수 있습니다. SQL 종속성이 등록되면 유효하지 않은 경우 알림이 즉시 발생하여 유효하지 않음을 알립니다. Visual Studio에서 내부 엔진 요구 사항을 SQL 엔진에 알리는 방법을 알기 때문에이 점에 대해 생각해보십시오.

따라서 SQLDep_OnChange 함수의 경우 이유에서 종속성이 해고되었습니다. 그 이유는 e 변수 (info, source 및 type)에 있습니다.이벤트 객체에 대한 세부 사항은 여기에서 찾을 수 있습니다 :

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

고마워요! 이 답변으로 지금은 약 2 일 동안 검색 및 시도에서 벗어났습니다. –

0

참조 : MS describesType 속성이 방법 특정한 경우 통지를 들어

무슨 종류의 SqlNotificationEventArgs가 처리기에 있습니다 (아래 정의 된대로). 당신이 수백 번 조회하고 그 유형이 매번 구독 할 때 당신의 SQL 문이 잘못되었다는 것을 알게된다면 - 다른 게시판의 가이드 라인을 참조하십시오.

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*/ 
... 
}