Laden...

SqlDependency funktioniert nur einmal

Erstellt von helda vor 10 Jahren Letzter Beitrag vor 10 Jahren 1.217 Views
H
helda Themenstarter:in
7 Beiträge seit 2008
vor 10 Jahren
SqlDependency funktioniert nur einmal

Hallo zusammen,

habe ein Problem mit SqlDependency funtioniert einmal wunderbar, bekommen als SqlNotificationEventArgs Info=Update, Source=Data, Type=Change. Nach erneutem registrieren funktioniert das ganze nicht mehr.

Die einstellungen in meiner Datenbank (SqlServer 2008 R2) müssten auch passen.


SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
SET CONCAT_NULL_YIELDS_NULL ON
SET QUOTED_IDENTIFIER ON
SET NUMERIC_ROUNDABORT OFF
SET ARITHABORT ON

Hier mein c# code:


public void startMonitoring()
        {
            logger.Info("StartMonitoring");
            String sql = "SELECT Value From dbo." + tableName;// +" WHERE Accessor=1 or Accessor=2";
            using (SqlCommand command = new SqlCommand(sql, this.connection.Connection))
            {

                command.Notification = null;
                SqlDependency testdependency = new SqlDependency(command);
                testdependency.OnChange += new OnChangeEventHandler(OnChange);
                using (SqlDataReader testreader = command.ExecuteReader())
                {
                    
                }
            }

        }
        public void OnChange(object sender, SqlNotificationEventArgs e)
        {
            Console.WriteLine(e.Info);
            this.startMonitoring();
            if (e.Info == SqlNotificationInfo.Update)
            {
                logger.Info("Update recived: " + e.Info);
                this.setValues();
            }
            
        }
public void restart()
        {
            this.dbConn.connect();
            this.connection.connect();
            SqlDependency.Start(connection.ConnectionString);
            
            this.startMonitoring();
        }

habe nicht wirklich eine Ahnung an was das liegen könnte.

Besten Dank im vorraus für eure Antworten.

T
708 Beiträge seit 2008
vor 10 Jahren

Ganz stumpf vermutet:
Du rufst restart() nicht in OnChange() auf?

Die Dependency wird immer nur einmal gefeuert, wie Du schon selbst schreibst. Anschließend muss die Registrierung erneut erfolgen. Das sehe ich in diesem Code allerdings nicht.

Gruß,
trib

[EDIT:] Zu schnell überflogen. Du rufst ja startMonitoring() nochmal auf.
Also ich habe das wie folgt gelöst:

        private void dependency_OnChange(object sender, SqlNotificationEventArgs e)
        {
            // Remove the handler, since it is only good
            // for a single notification.
            SqlDependency dependency = (SqlDependency)sender;
            dependency.OnChange -= dependency_OnChange;            

            // Invalid SQL-Query
            if (e.Info == SqlNotificationInfo.Invalid && e.Source == SqlNotificationSource.Statement && e.Type == SqlNotificationType.Subscribe)
            {            
                if (EventLog != null)
                    EventLog.WriteEntry("ungültiges SQL Statement. Die Dependency wird abgebrochen!");
                return;
            }

            ++_changeCount;
          
            // Reload the dataset that is bound to the grid.
            InitDependency();            
        }

private void InitDependency()
        {
            _dt.Clear();
            // Make sure the command object does not already have
            // a notification object associated with it.
            _command.Notification = null;

            SqlDependency dependency = new SqlDependency(_command);
            dependency.OnChange += new OnChangeEventHandler(dependency_OnChange);
            
            if (_connection.State == ConnectionState.Closed)
                _connection.Open();
            _dt.Load(_command.ExecuteReader(CommandBehavior.CloseConnection));

            foreach (DataRow row in _dt.Rows)
                if(EventLog != null)
                    EventLog.WriteEntry("EntryNo: " + row[0] + " ChangeCount: "+_changeCount.ToString());
                else
                    Console.WriteLine("EntryNo: " + row[0] + " ChangeCount: "+_changeCount.ToString());
        }

Wenn ich mich recht erinnere, ist es zwingend notwendig jedes Mal die Daten per DataTable.Load abzufragen. Sonst kam bei mir auch nur eine Meldung...

H
helda Themenstarter:in
7 Beiträge seit 2008
vor 10 Jahren

Hallo trib,

restart wird nur einmal aufgerufen, die erneute registrierung sollte in der startMonitoring funktion erfolgen.

2.207 Beiträge seit 2011
vor 10 Jahren

Hallo helda,

bitte beachte auch, dass es bei sowas einen minimalen Zeitraum gibt, in dem die Dependency nicht aktiviert ist. Nämlich nachdem sie gerade gefeuert wurde, bis sie wieder angehängt wird. Da bekommst du schlicht keine Events über. Oft ist das okay, aber nur als Hintergrund.

Gruss

Coffeebean

H
helda Themenstarter:in
7 Beiträge seit 2008
vor 10 Jahren

Hallo trib,

sollte eigentlich hiermit erledigt sein:


using (SqlDataReader testreader = command.ExecuteReader())
                {

                }

H
helda Themenstarter:in
7 Beiträge seit 2008
vor 10 Jahren

Hallo Coffeebean,

geht aber nach diesem Zeitraum auch nicht. das ich irgendwelche Änderungen nicht mitbekomme, habe ich dadurch gelöst das ich erst nach der registrierung die Daten abfrage.

H
helda Themenstarter:in
7 Beiträge seit 2008
vor 10 Jahren

Hallo zusammen,

Problem gelöst!!! 😁

Die SQLDependencies funktionierten einwandfrei. Der fehler war in einem anderen Teil meiner Applikation war ein Fehler. Dort wird der ThreadPool verwendet und durch einen Fehler wurde hier größenordnung alle 100ms versucht ca. 10 Threads zu holen.

Die SQLDependencies kamen dann nicht mehr zum Zug.