Question

I have a SqlDependency set up using the following query:

string sql = "SELECT dbo.Case.CMRID, dbo.Case.SolutionID, dbo.Case.CreateDT, dbo.Case.ModifyDT "
+ "FROM dbo.Case "
+ "WHERE dbo.Case.ModifyDT > @LastExecutionDateTime";

Executing this query causes the OnChanged event to fire continuously with a type of Invalid and Source of Statement. Which upon further research I found is what happens when your query breaks rules that are the same as the rules for indexed views since that is what this notification mechanism is based on.

Checking the Special Considerations Using Query Notifications (ADO.NET) I do not see any rules I am breaking with this statement.

Modifying the statement to

string sql = "SELECT dbo.Case.CMRID, dbo.Case.SolutionID, dbo.Case.CreateDT, dbo.Case.ModifyDT "
+ "FROM dbo.Case";

Does work correctly. The OnChanged event only fires when appropriate, and has the correct type set.

So, how can I only return records with a modify date since my last execution of the statement?

Was it helpful?

Solution

What type is ModifyDT?

The ADO.Net reference for QN is incomplete, the complete list is in the SQL reference at Creating a Query for Notification. The latter also lists the following:

The statement must not have comparison or expression based on double/real data types.

Another problem may be the cast from string to datetime that occurs in your query, which may be considered non-deterministic (which is a criteria listed by both ADO.Net and SQL spec). Try using a typed parameter instead: WHERE ModifyDT > @lastDateTime and pass in a parameter of type DateTime.

OTHER TIPS

You apparently have something that generates the date already in

LastExecutionDateTime

So rather than create a SqlDependency on the SQL, use a SqlCommand object

string sql = "SELECT CMRID, SolutionID, CreateDT, ModifyDT " + "FROM dbo.Case " + "WHERE ModifyDT > @lastExecutionDateTime"; 
//notice the parameter @lastExecutionDateTime, you cant use dates as a string, you also cant use something like CONVERT(datetime, '20040508'). You need a real date time object, hence the parameter

//You also only need to use the two part table ref (dbo.x) in the FROM clause, you dont need it on every field
//and while you didnt do it here, if anyone is interested a two part table ref in the form of dbo.[Case] would fail because the brackets will kill your dependency subscription

SqlCommand dependencyCommand= new SqlCommand(sql);
dependencyCommand.Parameters.Add(new SqlParameter("lastExecutionDateTime", SqlDbType.DateTime) {
        Value = LastExecutionDateTime 
    });

then just create your dependency on the command

//Create a dependency object and associate it with the SqlCommand.
SqlDependency dependency = new SqlDependency();
dependency.AddCommandDependency(dependencyCommand);
//Subscribe to the SqlDependency event.
dependency.OnChange += new OnChangeEventHandler(OnDependencyChange);

now get the current dataset and stick it in memory so you can use it to compare against once the dependency fires

//get the most recent data
DataTable currentDependencyData = new DataTable();
SqlDataAdapter dataAdapter = new SqlDataAdapter(dependencyCommand);
dataAdapter.Fill(currentDependencyData);

If you have not already figured this out, the 3 part table name that is the problem, try it like this.

"SELECT [CMRID], 
       [SolutionID], 
       [CreateDT], 
       [ModifyDT] 
FROM [dbo].[Case] 
WHERE [ModifyDT] > " + LastExecutionDateTime;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top