SQL依赖关系查询整个表

时间:2017-01-01 22:06:10

标签: c# sql-server database

我有一个使用SqlDependency监控数据库的控制台应用程序。该应用程序将监视数据库表,并在表中添加新记录后发送电子邮件。

一切正常,只是每次添加新记录时,将再次执行整个查询,并返回表中的所有记录。我真正想要的是只返回表中新添加的记录。

以下是我的代码:

SQLWatcher类:

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace TestApp
{
    public enum SqlWatcherNotificationType
    {
        Blocking,
        Threaded // Launch in another thread so SqlWatcher can immediately start monitoring again.
    }

    public class SqlWatcher : IDisposable
    {
        private string ConnectionString;
        private SqlConnection Connection;
        private SqlCommand Command;
        private SqlDataAdapter Adapter;
        private DataSet Result;
        private SqlWatcherNotificationType NotificationType;

        public SqlWatcher(string ConnectionString, SqlCommand Command, SqlWatcherNotificationType NotificationType)
        {
            this.NotificationType = NotificationType;
            this.ConnectionString = ConnectionString;

            SqlDependency.Start(this.ConnectionString);

            this.Connection = new SqlConnection(this.ConnectionString);
            this.Connection.Open();
            this.Command = Command;
            this.Command.Connection = this.Connection;

            Adapter = new SqlDataAdapter(this.Command);
        }

        public void Start()
        {
            RegisterForChanges();
        }

        public void Stop()
        {
            SqlDependency.Stop(this.ConnectionString);
        }

        public delegate void SqlWatcherEventHandler(DataSet Result);

        public event SqlWatcherEventHandler OnChange;

        public DataSet DataSet
        {
            get { return Result; }
        }

        private void RegisterForChanges()
        {
            // Remove old dependency object
            this.Command.Notification = null;

            // Create new dependency object
            SqlDependency dep = new SqlDependency(this.Command);
            dep.OnChange += new OnChangeEventHandler(Handle_OnChange);

            // Save data
            Result = new DataSet();
            Adapter.Fill(Result);

            // Notify client of change to DataSet
            switch (NotificationType)
            {
                case SqlWatcherNotificationType.Blocking:
                    OnChange(Result);
                    break;

                case SqlWatcherNotificationType.Threaded:
                    ThreadPool.QueueUserWorkItem(ChangeEventWrapper, Result);
                    break;
            }
        }

        public void ChangeEventWrapper(object state)
        {
            DataSet Result = (DataSet)state;
            OnChange(Result);
        }

        private void Handle_OnChange(object sender, SqlNotificationEventArgs e)
        {
            if (e.Type != SqlNotificationType.Change)
                throw new ApplicationException("Failed to create queue notification subscription!");

            //Clean up the old notification
            SqlDependency dep = (SqlDependency)sender;
            dep.OnChange -= Handle_OnChange;

            //Register for the new notification
            RegisterForChanges();
        }

        public void Dispose()
        {
            Stop();
        }
    }
}

实现:

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Linq;
using System.Data.SqlClient;
using System.Linq;
using System.Net.Mail;
using System.Text;
using System.Threading.Tasks;

namespace TestApp
{
    class Program
    {
        private static SqlWatcher SqlQueueWatcher;

        // string pin = string.Empty;
        string siteURL = "http://docapp/sites/nlpc";

        public string benefitCheck()
        {
            DataContext db = new DataContext("Data Source=;Initial Catalog=ServiceTest;User ID=;password =  ;Integrated Security=true");
            BenefitDocModel RSAName = new BenefitDocModel();
            CustomerCareContextDataContext LandingDb = new CustomerCareContextDataContext(siteURL);
            IEnumerable<BenefitDocModel> r = db.GetTable<BenefitDocModel>().ToList<BenefitDocModel>();

            var query = r.ToList();

            var rsa = from rr in query
                      select ( new { rr.PIN , rr.Document_Name, rr.Firstname, rr.Surname, rr.URL});

            foreach (var rsapin in rsa)
            {
                Console.WriteLine(rsapin);
                // sendEmail(rsapin.PIN);
            }
                /*pin = RSAName.PIN;
                RSAsLibraryDocument test = new RSAsLibraryDocument();
                BenefitDocModel RSAName1 = db.GetTable<BenefitDocModel>().FirstOrDefault(x => x.PIN == pin);
            if (pin == RSAName1.PIN)
                {
                    test.PIN = RSAName.PIN;
                    test.UserID = RSAName.UserID;
                    test.Firstname = RSAName.Firstname;
                    test.Surname = RSAName.Surname;
                    test.Document_Name = RSAName.Document_Name;
                    test.Document_URL = RSAName.URL;
                    test.UserType = RSAName.UserType;
                    test.Name = RSAName.PIN + RSAName.Document_Name;
                }*/
            return "success";

            }//

        public void SQLServiceStartForLog()
        {
            //BenefitDocModel rsapin = db.GetTable<BenefitDocModel>().FirstOrDefault(x => x.PIN == pin);
            //cmd.Notification = null;
            string connS = "Data Source=;Initial Catalog=ServiceTest;User ID=;password =  ;Integrated Security=true";
            SqlCommand cmd = new SqlCommand();
            //cmd.Notification = null;
            cmd = new SqlCommand("SELECT UserID, Surname, Firstname, PIN, URL, Document_Name FROM dbo.BenefitDoc");
            cmd.CommandType = CommandType.Text;
            SqlQueueWatcher = new SqlWatcher(connS, cmd, SqlWatcherNotificationType.Blocking);
            SqlQueueWatcher.OnChange += new SqlWatcher.SqlWatcherEventHandler(QueueSQLWatcher_OnChangeForLog);
            cmd.Notification = null;
            SqlQueueWatcher.Start();   
        }
        private void QueueSQLWatcher_OnChangeForLog(DataSet Result)
        {
            try
            {
                Console.WriteLine("Database monitoring is starting....");
                benefitCheck();
                Console.WriteLine("Database monitoring completed.");

            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }
        public void sendEmail(string pin)
        {
            MailMessage mail = new MailMessage("", "");
            SmtpClient client = new SmtpClient();
            client.Port = 25;
            client.DeliveryMethod = SmtpDeliveryMethod.Network;
            client.UseDefaultCredentials = false;
            client.Host = "smtp.gmail.com";
            client.EnableSsl = true;
            client.Credentials = new System.Net.NetworkCredential("", "");
            mail.Subject = "New Record added for RSA with " + pin;
            mail.Body = "The benefit application for user has been created.";
            client.Send(mail);
        }

        public static void Stop()
        {
            SqlQueueWatcher.Dispose();
        }
        static void Main(string[] args)
        {
            Program n = new Program();
            n.SQLServiceStartForLog();
            Console.ReadLine();
        }
    }
}

1 个答案:

答案 0 :(得分:0)

这不是SqlDependency的工作原理。基本上它的工作方式是给它一个查询,如果查询结果发生变化,它会触发一个通知。但是当您执行datareader时,它不仅会返回更改。它返回的数据就像是常规查询一样。

如果您只想获得更改,那么您需要在表格中添加LastModifiedDateTime之类的列,然后查询LastModifiedDateTime大于最后检索记录时的记录时间。

或者,有this NuGet包,如果您有兴趣使用它,它会为您做这类事情。