IT

c#을 사용하여 SQL Server 테이블 변경을 감시하는 방법

itgroup 2023. 4. 13. 20:45
반응형

c#을 사용하여 SQL Server 테이블 변경을 감시하는 방법

동일한 DB에 액세스하는 여러 응용 프로그램이 있으며 이러한 응용 프로그램 중 하나가 특정 테이블에서 변경(업데이트, 삽입)되면 알림을 받아야 합니다.

데이터베이스와 앱이 같은 서버에 없습니다.

완전성을 위해 SQLDependency(및 SQLTableDependency) 클래스에 의존하는 솔루션보다 더 정통적인 솔루션이 몇 가지 있습니다.SqlDependency는 원래 분산 웹 서버 캐시의 갱신을 쉽게 하도록 설계되었기 때문에 이벤트 제작자로 설계된 경우와는 다른 요건에 따라 구축되었습니다.

대략 4가지 옵션이 있으며, 그 중 일부는 아직 여기에서 다루지 않았습니다.

  • 변경 추적
  • CDC
  • 큐에 트리거
  • CLR

변경 추적

출처 : https://learn.microsoft.com/en-us/sql/relational-databases/track-changes/about-change-tracking-sql-server

변경 추적은 SQL Server의 경량 알림 메커니즘입니다.기본적으로 데이터를 변경할 때마다 데이터베이스 전체의 버전 번호가 증가합니다.버전 번호는 변경된 컬럼의 이름을 포함한 비트마스크를 사용하여 변경 추적 테이블에 기록됩니다.실제 변경은 지속되지 않습니다.통지에는 특정 데이터 엔티티가 변경된 정보만 포함됩니다.또한 변경 테이블 버전 관리는 누적되므로 개별 항목에 대한 변경 통지는 유지되지 않고 새로운 통지에 의해 덮어씁니다.즉, 엔티티가 두 번 변경되면 변경 추적은 최신 변경만 인식합니다.

이러한 변경을 c# 로 취득하려면 , 폴링을 사용할 필요가 있습니다.변경 추적 테이블을 폴링하고 각 변경을 검사하여 해당 여부를 확인할 수 있습니다.관심 있는 경우 데이터로 직접 이동하여 현재 상태를 검색해야 합니다.

데이터 캡처 변경

출처 : https://technet.microsoft.com/en-us/library/bb522489(v=sql.105).aspx

변경 데이터 캡처(CDC)는 변경 추적보다 강력하지만 비용이 가장 많이 듭니다.변경 데이터 캡처는 데이터베이스 로그 모니터링을 기반으로 변경 내용을 추적하고 알립니다.따라서 CDC는 변경된 실제 데이터에 액세스할 수 있으며 모든 개별 변경 사항을 기록합니다.

변경 트래킹과 마찬가지로 c#에서 이러한 변경을 캡처하려면 폴링을 사용해야 합니다.단, CDC의 경우 폴링된 정보에는 변경 내용이 포함되어 있기 때문에 데이터 자체로 돌아갈 필요는 없습니다.

큐로 트리거 - 이 메서드는 사용되지 않습니다.

이 기술은 알림이 필요한 테이블의 트리거에 따라 달라집니다.변경할 때마다 트리거가 발생하며 트리거는 이 정보를 서비스 브로커 큐에 씁니다.다음으로 큐는 Service Broker Message Processor(위 링크의 샘플)를 사용하여 C# 경유로 에 접속할 수 있습니다.

변경 추적 또는 CDC와 달리 큐에 대한 트리거는 폴링에 의존하지 않기 때문에 실시간이벤트를 제공합니다

CLR

이것은 제가 본 적이 있는 기술이지만 추천하지 않습니다.외부 통신에 CLR에 의존하는 솔루션은 기껏해야 해킹에 불과합니다.CLR은 C#을 활용하여 복잡한 데이터 처리 코드를 쉽게 작성할 수 있도록 설계되었습니다.메시징 라이브러리와 같은 외부 종속성을 배선하도록 설계되지 않았습니다.또한 CLR 바인딩 작업은 클러스터 환경에서 예측할 수 없는 방식으로 중단될 수 있습니다.

즉, 셋업은 매우 간단합니다.메시지 어셈블리를 CLR에 등록하면 트리거 또는 SQL 작업을 사용하여 콜아웃할 수 있기 때문입니다.

요약하면...

Microsoft가 이 문제에 대한 대응을 완강히 거부해 온 것은, 항상 경악의 대상이었습니다.데이터베이스에서 코드로의 이벤트는 데이터베이스 제품의 기본 제공 기능이어야 합니다.Oracle Advanced Queuing과 ODP.net의 Message Available 이벤트를 조합하여 10여 년에 C#에 대한 신뢰성 높은 데이터베이스 이벤트를 제공했다는 점을 감안하면 MS는 매우 안타까운 일입니다.

결론은 이 질문에 대해 제시된 어떤 솔루션도 그다지 만족스럽지 않다는 것입니다.모두 기술적인 단점이 있어 셋업 비용이 많이 듭니다.듣고 계신다면, 이 유감스러운 상황을 정리해 주세요.

를 사용할 수 있습니다.그 용도는 대부분 ASP용입니다.NET 페이지(클라이언트 알림의 수가 적음).

ALTER DATABASE UrDb SET ENABLE_BROKER

「 」의 실장OnChange다음 중 하나:

void OnChange(object sender, SqlNotificationEventArgs e)

코드:

SqlCommand cmd = ...
cmd.Notification = null;

SqlDependency dependency = new SqlDependency(cmd);

dependency.OnChange += OnChange;

(메시지 기반 통신 플랫폼)을 사용하여 데이터베이스 엔진에서 메시지를 수신합니다.

일반적으로 Service Broker를 사용합니다.

이것은 트리거 -> 큐 -> 어플리케이션입니다.

다른 답변을 확인한 후 편집:

참고로 "Query Notifications"는 서비스 브로커를 기반으로 구축되어 있습니다.

편집 2:

기타 링크

SQLTableDependency를 사용합니다.레코드가 변경되면 이벤트가 발생하는 c# 컴포넌트입니다.기타 자세한 내용은 https://github.com/christiandelbianco/monitor-table-change-with-sqltabledependency에서 확인할 수 있습니다.

와 유사하다.NET SqlDependency(SqlTableDependency)는 변경/삭제 또는 갱신된 데이터베이스 테이블 값을 포함하는 이벤트를 발생시킵니다.

string conString = "data source=.;initial catalog=myDB;integrated security=True";

using(var tableDependency = new SqlTableDependency<Customers>(conString))
{
    tableDependency.OnChanged += TableDependency_Changed;
    tableDependency.Start();

    Console.WriteLine("Waiting for receiving notifications...");
    Console.WriteLine("Press a key to stop");
    Console.ReadKey();
}
...
...
void TableDependency_Changed(object sender, RecordChangedEventArgs<Customers> e)
{
    if (e.ChangeType != ChangeType.None)
    {
        var changedEntity = e.Entity;
        Console.WriteLine("DML operation: " + e.ChangeType);
        Console.WriteLine("ID: " + changedEntity.Id);
        Console.WriteLine("Name: " + changedEntity.Name);
        Console.WriteLine("Surname: " + changedEntity.Surname);
    }
}

SQLDependency는 사용자가 지정한SqlCommand를 감시하지 않습니다.따라서 1개 프로젝트의 데이터베이스에 값을 삽입하고 다른 프로젝트에서 해당 이벤트를 캡처하려고 하면 SQLDependency를 생성할 때 데이터베이스가 아닌 1개 프로젝트의 SqlCommand에서 이벤트가 생성되었기 때문에 작동하지 않습니다.SqlCommand는 해당 프로젝트의 해당 명령을 사용해야만 변경 이벤트를 생성합니다.

SqlDependency 클래스를 사용할 때는 메모리 누수에 문제가 있으므로 주의하십시오.

크로스 플랫폼만 사용합니다.NET 3.5,NET Core 호환 오픈 소스 솔루션 - Sql Dependency Ex.변경된 데이터와 함께 통지를 받을 수 있습니다(알림 이벤트 개체의 속성을 통해 액세스할 수 있습니다).DELETE\UPDATE\도 사용할 수 있습니다.INSERT 작업은 개별적으로 또는 함께 수행합니다.

다음은 SQLDependency를 쉽게 사용할 수 있음을 보여주는 예입니다.:

int changesReceived = 0;
using (SqlDependencyEx sqlDependency = new SqlDependencyEx(
          TEST_CONNECTION_STRING, TEST_DATABASE_NAME, TEST_TABLE_NAME)) 
{
    sqlDependency.TableChanged += (o, e) => changesReceived++;
    sqlDependency.Start();

    // Make table changes.
    MakeTableInsertDeleteChanges(changesCount);

    // Wait a little bit to receive all changes.
    Thread.Sleep(1000);
}

Assert.AreEqual(changesCount, changesReceived);

자세한 내용은 링크를 참조하십시오.이 컴포넌트는 많은 엔터프라이즈 레벨의 애플리케이션에서 테스트되어 신뢰성이 검증되었습니다.이게 도움이 됐으면 좋겠다.

SQL Server 2005부터는 쿼리 알림을 사용할 수 있습니다. 쿼리 알림은 ADO에서 활용할 수 있습니다.NET, http://msdn.microsoft.com/en-us/library/t9x04ed2.aspx 참조해 주세요.

아키텍처가 완전히 잘못된 것 같습니다.또한 통지해야 할 앱의 종류를 지정하지 않았습니다(웹앱/콘솔앱/윈폼/서비스 등).

그럼에도 불구하고, 당신의 질문에 답하기 위해, 이것을 해결하는 방법은 여러 가지가 있습니다.다음을 사용할 수 있습니다.

1) 두 번째 앱의 다음 업데이트 세트가 첫 번째 앱의 업데이트와 충돌하지 않는지 확인하는 데만 관심이 있는 경우 타임스탬프

2) sql 의존관계 오브젝트 - 자세한 내용은 http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqldependency.aspx를 참조하십시오.

3) 여러 클라이언트(Web/winform/Service)가 가입하여 변경 시 알림을 받을 수 있는 커스텀 푸시 알림 서비스

즉, 통지 요건의 복잡성과 사용 목적에 따라 가장 간단하고 쉽고 저렴한(노력 면에서) 솔루션을 사용해야 합니다.단순한 데이터 동시성이 유일한 요건인 경우 지나치게 복잡한 알림 시스템을 구축하지 마십시오(이 경우 단순한 타임스탬프 기반 솔루션을 사용합니다).

시스템은 DNS 등의 하는 것으로 되었습니다.시스템은 DNS 동기화 등의 구조에서 동작하는 것으로 검증되었습니다. 하려면 테이블 .decimal ★★★★★★★★★★★★★★★★★」bigint.감시할 필요가 있는 각 테이블에서 삽입, 갱신 및 삭제 시 트리거를 만듭니다.이 트리거는 실행 시 버전 관리 테이블의 적절한 테이블버전을 증가시킵니다.모니터링되는 테이블이 자주 변경될 것으로 예상되는 경우 버전 재사용을 위해 프로비저닝해야 합니다.마지막으로 응용 프로그램에서는 모니터링 대상 테이블을 쿼리할 때마다 해당 버전의 쿼리 및 저장도 수행합니다.앱에서 모니터링되는 테이블을 변경할 때 먼저 현재 버전을 쿼리하고 버전이 변경되지 않은 경우에만 변경 사항을 처리합니다.하도록 할 수.sql proc는 proc로 동작합니다.이것은 지극히 심플하지만 실증이 끝난 솔리드 솔루션입니다.특정 기능상의 용도(데이터의 일관성을 확보하기 위해)가 있으며 리소스도 가볍습니다(중개 이벤트를 감시하지 않는 경우는 발생하지 않습니다).단, 이벤트가 발생할 때까지 수동적으로 대기하는 것이 아니라 변경을 적극적으로 체크하는 어플리케이션이 필요합니다.

이것은 통지는 아니지만 제목에 monitor라고 기재되어 있기 때문에 그 시나리오에 적합할 수 있습니다.

SQL Server 타임스탬프 열을 사용하면 쿼리 간의 변경(계속 지속되는)을 쉽게 볼 수 있습니다.

SQL Server 타임스탬프 열 유형은 시간과 전혀 관련이 없기 때문에 이름이 잘못 지정되었습니다. 삽입 또는 업데이트 시 자동으로 증가하는 데이터베이스 전체 값입니다.원하는 테이블에서 Max(timestamp)를 선택하거나 삽입한 행에서 타임스탬프를 반환한 후 timestamp > storedTimestamp 위치를 선택하면 그 사이에 갱신 또는 삽입된 모든 결과가 나타납니다.

또한 데이터베이스 전체 값이기 때문에 저장된 타임스탬프를 사용하여 저장된 타임스탬프를 마지막으로 확인/업데이트한 이후 테이블에 데이터가 기록되었는지 확인할 수 있습니다.

1-이름 붙일 새 데이터베이스 만들기TestNotification

2-이름에 새 테이블 추가Customers필드:Id,Name,Family

3-이네이블화해야합니다.ServiceBroker

sql에서 이 코드를 4회 실행합니다.

ALTER DATABASE [TestNotification] SET ENABLE_BROKER WITH ROLLBACK IMMEDIATE

5개의 새로운 프로젝트 생성c# consoleApp

6 인스톨SqlTableDependency도서관nuget

7 - 이름을 붙일 클래스 만들기Customer

public class Customer
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Family { get; set; }
}

8인치Program.cs이 코드를 작성하다

        static void Main(string[] args)
        {
            var connectionString = "data source=.;initial catalog=TestNotification;integrated security=true;";
            using (var tableDependecy = new SqlTableDependency<Customer>(connectionString, "Customers"))
            {
                tableDependecy.OnChanged += TableDependency_Changed;
                tableDependecy.OnError += TableDependency_OnError;

                tableDependecy.Start();

                Console.WriteLine("Waiting");

                Console.ReadKey();
                tableDependecy.Stop();
            }
        }

        static void TableDependency_Changed(object sender, RecordChangedEventArgs<Customer> e)
        {
            Console.WriteLine(Environment.NewLine);
            if (e.ChangeType != ChangeType.None)
            {
                var changeEntity = e.Entity;
                Console.WriteLine("ChangeType: " + e.ChangeType);
                Console.WriteLine("Id: " + changeEntity.Id);
                Console.WriteLine("Name: " + changeEntity.Name);
                Console.WriteLine("Id: " + changeEntity.Family);
                Console.WriteLine(Environment.NewLine);
            }
        }

        static void TableDependency_OnError(object sender, ErrorEventArgs e)
        {
            Console.WriteLine(e.Message);
        }

언급URL : https://stackoverflow.com/questions/5288434/how-to-monitor-sql-server-table-changes-by-using-c

반응형