Teilen über


Definieren einer logische Datensatzbeziehung zwischen Mergetabellenartikeln

Gilt für: SQL Server

In diesem Thema wird beschrieben, wie eine logische Datensatzbeziehung zwischen Mergetabellenartikeln in SQL Server mit SQL Server Management Studio, Transact-SQL oder Replikationsverwaltungsobjekten (Replication Management Objects, RMO) definiert wird.

Mergereplikation ermöglicht Ihnen, eine Beziehung zwischen verknüpften Zeilen in verschiedenen Tabellen zu definieren. Diese Zeilen können dann während der Synchronisierung als Transaktionseinheit verarbeitet werden. Eine logische Datensatzbeziehung zwischen zwei Artikeln kann unabhängig davon definiert werden, ob sie über eine Joinfilterbeziehung verfügen oder nicht. Weitere Informationen finden Sie unter Gruppieren von Änderungen an verknüpften Zeilen mithilfe von logischen Datensätzen.

Hinweis

Diese Funktion wird in einer zukünftigen Version von SQL Serverentfernt. Nutzen Sie diese Funktionen bei Neuentwicklungen nicht mehr, und planen Sie die Änderung von Anwendungen, die diese Funktion zurzeit verwenden.

In diesem Thema

Vorbereitungen

Einschränkungen

  • Wenn Sie einen logischen Datensatz hinzufügen, ändern oder löschen, nachdem Abonnements für die Veröffentlichung initialisiert wurden, müssen Sie eine neue Momentaufnahme generieren und alle Abonnements nach vorgenommener Änderung erneut initialisieren. Weitere Informationen zum Ändern von Eigenschaften finden Sie unter Ändern von Veröffentlichungs- und Artikeleigenschaften.

Verwendung von SQL Server Management Studio

Zum Definieren logischer Datensätze steht Ihnen das Dialogfeld Join hinzufügen zur Verfügung, das über den Assistenten für neue Veröffentlichung und das Dialogfeld Veröffentlichungseigenschaften – <Veröffentlichung> verfügbar ist. Weitere Informationen zum Verwenden des Assistenten sowie Zugriff auf das Dialogfeld finden Sie unter Erstellen einer Veröffentlichung und Anzeigen und Ändern von Veröffentlichungseigenschaften.

Logische Datensätze können nur dann im Dialogfeld Join hinzufügen definiert werden, wenn sie auf einen Joinfilter in einer Mergeveröffentlichung angewendet werden und die Veröffentlichung die Anforderungen für die Verwendung vorausberechneter Partitionen erfüllt. Wenn Sie logische Datensätze definieren möchten, die nicht auf Joinfilter angewendet werden, und die Konflikterkennung und -lösung auf der Ebene des logischen Datensatzes festlegen möchten, müssen Sie gespeicherte Prozeduren verwenden.

So definieren Sie eine logische Datensatzbeziehung

  1. Wählen Sie auf der Seite Tabellenzeilen filtern des Assistenten für neue Veröffentlichung oder auf der Seite Zeilen filtern des Dialogfelds Veröffentlichungseigenschaften – <Veröffentlichung> im Bereich Gefilterte Tabellen einen Zeilenfilter aus.

    Logische Datensatzbeziehungen sind mit einem Joinfilter verknüpft, der wiederum einen Zeilenfilter erweitert. Sie müssen daher zuerst einen Zeilenfilter definieren, bevor Sie den Filter mit einem Join erweitern und eine logische Datensatzbeziehung anwenden können. Nach dem Definieren eines Joinfilters können Sie diesen Joinfilter wiederum um einen anderen Joinfilter erweitern. Weitere Informationen zum Definieren von Joinfiltern finden Sie unter Definieren und Ändern eines Verknüpfungsfilters zwischen Mergeartikeln.

  2. Klicken Sie auf Hinzufügenund anschließend auf Join hinzufügen, um den ausgewählten Filter zu erweitern.

  3. Definieren Sie im Dialogfeld Join hinzufügen einen Joinfilter, und aktivieren Sie dann das Kontrollkästchen Logischer Datensatz.

  4. Wenn Sie sich im Dialogfeld Veröffentlichungseigenschaften.-.<Veröffentlichung> befinden, klicken Sie auf OK, um zu speichern und das Dialogfeld zu schließen.

So löschen Sie eine logische Datensatzbeziehung

  • Sie können entweder nur die logische Datensatzbeziehung oder die logische Datensatzbeziehung und den zugeordneten Joinfilter gemeinsam löschen.

    So löschen Sie nur die logische Datensatzbeziehung:

    1. Wählen Sie im Assistenten für neue Veröffentlichung auf der Seite Zeilen filtern oder im Dialogfeld Veröffentlichungseigenschaften – <Veröffentlichung> auf der Seite Zeilen filtern im Bereich Gefilterte Tabellen den der logischen Datensatzbeziehung zugeordneten Joinfilter aus, und klicken Sie dann auf Bearbeiten.

    2. Deaktivieren Sie im Dialogfeld Join bearbeiten die Option Logischer Datensatz.

    3. Wählen Sie OK aus.

    So löschen Sie die logische Datensatzbeziehung und den zugeordneten Joinfilter:

    • Wählen Sie im Assistenten für neue Veröffentlichung auf der Seite Zeilen filtern bzw. im Dialogfeld Veröffentlichungseigenschaften – <Veröffentlichung> im Bereich Gefilterte Tabellen den betreffenden Filter aus, und klicken Sie dann auf Löschen. Wenn der Joinfilter, den Sie löschen möchten, mit anderen Joins erweitert ist, werden diese Joins beim Löschen des Filters selbst ebenfalls gelöscht.

Verwenden von Transact-SQL

Sie können logische Datensatzbeziehungen zwischen Artikeln programmgesteuert mithilfe gespeicherter Replikationsprozeduren angeben.

So definieren Sie eine logische Datensatzbeziehung ohne einen zugeordneten Joinfilter

  1. Wenn die Veröffentlichung irgendwelche gefilterten Artikel enthält, führen Sie sp_helpmergepublicationaus, und achten Sie im Resultset auf den Wert von use_partition_groups .

    • Wenn der Wert 1ist, dann werden bereits vorausberechnete Partitionen verwendet.

    • Ist der in Schritt 1 ermittelte Wert 0, führen Sie sp_changemergepublication auf dem Verleger für die Veröffentlichungsdatenbank aus. Geben Sie den Wert use_partition_groups für @property und den Wert true für @valuean.

      Hinweis

      Wenn die Veröffentlichung keine vorausberechneten Partitionen unterstützt, dann können keine logischen Datensätze verwendet werden. Weitere Informationen finden Sie unter „Anforderungen für die Verwendung vorausberechneter Partitionen“ im Thema Optimieren der Leistung parametrisierter Filter mithilfe vorausberechneter Partitionen.

    • Ist der Wert NULL, muss der Momentaufnahme-Agent ausgeführt werden, um die Momentaufnahme für die Veröffentlichung zu generieren.

  2. Wenn die Artikel, die den logischen Datensatz umfassen, nicht vorhanden sind, führen Sie sp_addmergearticle auf dem Verleger für die Veröffentlichungsdatenbank aus. Geben Sie eine der folgenden Konflikterkennungs- und -lösungsoptionen für den logischen Datensatz an:

    • Damit Konflikte, die innerhalb verknüpfter Zeilen im logischen Datensatz auftreten, erkannt und gelöst werden, geben Sie den Wert true für @logical_record_level_conflict_detection und @logical_record_level_conflict_resolutionan.

    • Um die Standard-Konflikterkennung und -lösung auf Zeilen- oder Spaltenebene zu verwenden, geben Sie den Wert false für @logical_record_level_conflict_detection und @logical_record_level_conflict_resolutionan.

  3. Wiederholen Sie Schritt 2 für jeden Artikel, der den logischen Datensatz umfasst. Sie müssen für jeden Artikel im logischen Datensatz die gleiche Konflikterkennung und Konfliktlösungsoption verwenden. Weitere Informationen finden Sie unter Ermitteln und Lösen von Konflikten in logischen Datensätzen.

  4. Führen Sie auf dem Verleger für die Veröffentlichungsdatenbank sp_addmergefilteraus. Geben Sie @publicationan sowie den Namen des ersten an der Beziehung beteiligten Artikels für @article, den Namen des zweiten an der Beziehung beteiligten Artikels für @join_articlename, einen Namen für die Beziehung für @filtername, eine Klausel zur Definition der Beziehung zwischen den beiden Artikeln für @join_filterclause, den Jointyp für @join_unique_key und einen der folgenden Werte für @filter_type:

    • 2 – Definiert eine logische Datensatzbeziehung.

    • 3 – Definiert eine logische Beziehung mit einem Joinfilter.

    Hinweis

    Wird kein Joinfilter verwendet, ist die Richtung der Beziehung zwischen den beiden Artikeln nicht wichtig.

  5. Wiederholen Sie Schritt 2 für jede weitere logische Datensatzbeziehung in der Veröffentlichung.

So ändern Sie die Konflikterkennung und -lösung für logische Datensätze

  1. So erkennen und lösen Sie Konflikte, die innerhalb verknüpfter Zeilen im logischen Datensatz auftreten:

    • Führen Sie auf dem Verleger für die Veröffentlichungsdatenbank sp_changemergearticleaus. Geben Sie den Wert logical_record_level_conflict_detection für @property und den Wert true für @valuean. Geben Sie den Wert 1 für @force_invalidate_snapshot und @force_reinit_subscriptionan.

    • Führen Sie auf dem Verleger für die Veröffentlichungsdatenbank sp_changemergearticleaus. Geben Sie den Wert logical_record_level_conflict_resolution für @property und den Wert true für @valuean. Geben Sie den Wert 1 für @force_invalidate_snapshot und @force_reinit_subscriptionan.

  2. So verwenden Sie die Standard-Konflikterkennung und -lösung auf Zeilen- oder Spaltenebene:

    • Führen Sie auf dem Verleger für die Veröffentlichungsdatenbank sp_changemergearticleaus. Geben Sie den Wert logical_record_level_conflict_detection für @property und den Wert false für @valuean. Geben Sie den Wert 1 für @force_invalidate_snapshot und @force_reinit_subscriptionan.

    • Führen Sie auf dem Verleger für die Veröffentlichungsdatenbank sp_changemergearticleaus. Geben Sie den Wert logical_record_level_conflict_resolution für @property und den Wert false für @valuean. Geben Sie den Wert 1 für @force_invalidate_snapshot und @force_reinit_subscriptionan.

So entfernen Sie eine logische Datensatzbeziehung

  1. Führen Sie auf dem Verleger für die Veröffentlichungsdatenbank die folgende Abfrage aus, um alle Informationen über die für die angegebene Veröffentlichung definierten logischen Datensatzbeziehungen zurückzugeben:

    SELECT f.* FROM sysmergesubsetfilters AS f 
    INNER JOIN sysmergepublications AS p
    ON f.pubid = p.pubid WHERE p.[name] = @publication;
    

    Achten Sie auf den Namen der zu entfernenden logischen Datensatzbeziehung in der Spalte filtername des Resultsets.

    Hinweis

    Diese Abfrage gibt die gleichen Informationen zurück wie sp_helpmergefilter. Diese gespeicherte Systemprozedur ermittelt jedoch nur Informationen über logische Datensatzbeziehungen, die auch Joinfilter sind.

  2. Führen Sie auf dem Verleger für die Veröffentlichungsdatenbank sp_dropmergefilteraus. Geben Sie @publicationan sowie den Namen eines der an der Beziehung beteiligten Artikel für @articleund den Namen der Beziehung aus Schritt 1 für @filtername.

Beispiel (Transact-SQL)

Im folgenden Beispiel werden vorausberechnete Partitionen für eine vorhandene Veröffentlichung aktiviert und ein logischer Datensatz erstellt, der die zwei neuen Artikel für die Tabellen SalesOrderHeader und SalesOrderDetail umfasst.

-- Remove ON DELETE CASCADE from FK_SalesOrderDetail_SalesOrderHeader_SalesOrderID;
-- logical records cannot be used with ON DELETE CASCADE. 
IF EXISTS (SELECT * FROM sys.objects 
WHERE name = 'FK_SalesOrderDetail_SalesOrderHeader_SalesOrderID')
BEGIN
    ALTER TABLE [Sales].[SalesOrderDetail] 
    DROP CONSTRAINT [FK_SalesOrderDetail_SalesOrderHeader_SalesOrderID] 
END

ALTER TABLE [Sales].[SalesOrderDetail]  
WITH CHECK ADD CONSTRAINT [FK_SalesOrderDetail_SalesOrderHeader_SalesOrderID] 
FOREIGN KEY([SalesOrderID])
REFERENCES [Sales].[SalesOrderHeader] ([SalesOrderID])
GO

DECLARE @publication    AS sysname;
DECLARE @table1 AS sysname;
DECLARE @table2 AS sysname;
DECLARE @table3 AS sysname;
DECLARE @salesschema AS sysname;
DECLARE @hrschema AS sysname;
DECLARE @filterclause AS nvarchar(1000);
DECLARE @partitionoption AS bit;
SET @publication = N'AdvWorksSalesOrdersMerge'; 
SET @table1 = N'SalesOrderDetail'; 
SET @table2 = N'SalesOrderHeader'; 
SET @salesschema = N'Sales';
SET @hrschema = N'HumanResources';
SET @filterclause = N'Employee.LoginID = HOST_NAME()';

-- Ensure that the publication uses precomputed partitions.
SET @partitionoption = (SELECT [use_partition_groups] FROM sysmergepublications 
    WHERE [name] = @publication);
IF @partitionoption <> 1
BEGIN
    EXEC sp_changemergepublication 
        @publication = @publication, 
        @property = N'use_partition_groups', 
        @value = 'true',
        @force_invalidate_snapshot = 1;
END  

-- Add a filtered article for the Employee table.
EXEC sp_addmergearticle 
  @publication = @publication, 
  @article = @table1, 
  @source_object = @table1, 
  @type = N'table', 
  @source_owner = @hrschema,
  @schema_option = 0x0004CF1,
  @description = N'article for the Employee table',
  @subset_filterclause = @filterclause;

-- Add an article for the SalesOrderHeader table.
EXEC sp_addmergearticle 
  @publication = @publication, 
  @article = @table2, 
  @source_object = @table2, 
  @type = N'table', 
  @source_owner = @salesschema,
  @schema_option = 0x0034EF1,
  @description = N'article for the SalesOrderHeader table';

-- Add an article for the SalesOrderDetail table.
EXEC sp_addmergearticle 
  @publication = @publication, 
  @article = @table3, 
  @source_object = @table3, 
  @source_owner = @salesschema,
  @description = 'article for the SalesOrderDetail table', 
  @identityrangemanagementoption = N'auto', 
  @pub_identity_range = 100000, 
  @identity_range = 100, 
  @threshold = 80;

-- Add a merge join filter between Employee and SalesOrderHeader.
EXEC sp_addmergefilter 
  @publication = @publication, 
  @article = @table2, 
  @filtername = N'SalesOrderHeader_Employee', 
  @join_articlename = @table1, 
  @join_filterclause = N'Employee.EmployeeID = SalesOrderHeader.SalesPersonID', 
  @join_unique_key = 1, 
  @filter_type = 1, 
  @force_invalidate_snapshot = 1, 
  @force_reinit_subscription = 1;

-- Create a logical record relationship that is also a merge join 
-- filter between SalesOrderHeader and SalesOrderDetail.
EXEC sp_addmergefilter 
  @publication = @publication, 
  @article = @table3, 
  @filtername = N'LogicalRecord_SalesOrderHeader_SalesOrderDetail', 
  @join_articlename = @table2, 
  @join_filterclause = N'[SalesOrderHeader].[SalesOrderID] = [SalesOrderDetail].[SalesOrderID]', 
  @join_unique_key = 1, 
  @filter_type = 3, 
  @force_invalidate_snapshot = 1, 
  @force_reinit_subscription = 1;
GO

Verwenden von Replikationsverwaltungsobjekten (RMO)

Hinweis

Bei der Mergereplikation können Sie auch angeben, dass Konflikte auf der Ebene logischer Datensätze nachverfolgt und gelöst werden. Diese Optionen können mit RMO jedoch nicht festgelegt werden.

So definieren Sie eine logische Datensatzbeziehung ohne einen zugeordneten Joinfilter

  1. Erstellen Sie eine Verbindung mit dem Verleger, indem Sie die ServerConnection -Klasse verwenden.

  2. Erstellen Sie eine Instanz der MergePublication -Klasse, legen Sie die Name -Eigenschaft und die DatabaseName -Eigenschaft der Veröffentlichung fest, und legen Sie die ConnectionContext -Eigenschaft auf die in Schritt 1 erstellte Verbindung fest.

  3. Rufen Sie die LoadProperties -Methode auf, um die Eigenschaften des Objekts abzurufen. Wenn diese Methode falsezurückgibt, sind die Veröffentlichungseigenschaften in Schritt 2 falsch definiert, oder die Veröffentlichung ist nicht vorhanden.

  4. Wenn die PartitionGroupsOption -Eigenschaft auf Falsefestgelegt ist, ändern Sie sie in True.

  5. Wenn die Artikel, die den logischen Datensatz enthalten sollen, nicht vorhanden sind, erstellen Sie eine Instanz der MergeArticle -Klasse, und legen Sie die folgenden Eigenschaften fest:

    • Den Namen des Artikels für Name

    • Den Namen der Veröffentlichung für PublicationName.

    • (Optional) Wenn der Artikel horizontal gefiltert wird, geben Sie die Zeilenfilterklausel für die FilterClause -Eigenschaft an. Verwenden Sie diese Eigenschaft, um einen statischen oder parametrisierten Zeilenfilter anzugeben. Weitere Informationen zu parametrisierten Zeilenfiltern finden Sie unter Parametrisierte Zeilenfilter.

    Weitere Informationen finden Sie unter Definieren eines Artikels.

  6. Rufen Sie die Create-Methode auf.

  7. Wiederholen Sie die Schritte 5 und 6 für jeden Artikel, der den logischen Datensatz umfasst.

  8. Erstellen Sie eine Instanz der MergeJoinFilter -Klasse, um die logische Datensatzbeziehung zwischen Artikeln zu definieren. Legen Sie dann die folgenden Eigenschaften fest:

  9. Rufen Sie die AddMergeJoinFilter -Methode für das Objekt auf, das den untergeordneten Artikel in der Beziehung darstellt. Übergeben Sie das MergeJoinFilter -Objekt aus Schritt 8, um die Beziehung zu definieren.

  10. Wiederholen Sie die Schritte 8 und 9 für jede weitere logische Datensatzbeziehung in der Veröffentlichung.

Beispiel (RMO)

In diesem Beispiel wird ein logischer Datensatz erstellt, der die zwei neuen Artikel für die Tabellen SalesOrderHeader und SalesOrderDetail umfasst.

           // Define the Publisher and publication names.
           string publisherName = publisherInstance;
           string publicationName = "AdvWorksSalesOrdersMerge";
           string publicationDbName = "AdventureWorks2022";

           // Specify article names.
           string articleName1 = "SalesOrderHeader";
           string articleName2 = "SalesOrderDetail";
           
           // Specify logical record information.
           string lrName = "SalesOrderHeader_SalesOrderDetail";
           string lrClause = "[SalesOrderHeader].[SalesOrderID] = "
               + "[SalesOrderDetail].[SalesOrderID]";

           string schema = "Sales";

           MergeArticle article1 = new MergeArticle();
           MergeArticle article2 = new MergeArticle();
           MergeJoinFilter lr = new MergeJoinFilter();
           MergePublication publication = new MergePublication();

           // Create a connection to the Publisher.
           ServerConnection conn = new ServerConnection(publisherName);

           try
           {
               // Connect to the Publisher.
               conn.Connect();

               // Verify that the publication uses precomputed partitions.
               publication.Name = publicationName;
               publication.DatabaseName = publicationDbName;
               publication.ConnectionContext = conn;

               // If we can't get the properties for this merge publication, then throw an application exception.
               if (publication.LoadProperties())
               {
                   // If precomputed partitions is disabled, enable it.
                   if (publication.PartitionGroupsOption == PartitionGroupsOption.False)
                   {
                       publication.PartitionGroupsOption = PartitionGroupsOption.True;
                   }
               }
               else
               {
                   throw new ApplicationException(String.Format(
                       "Settings could not be retrieved for the publication. " +
                       "Ensure that the publication {0} exists on {1}.",
                       publicationName, publisherName));
               }

               // Set the required properties for the PurchaseOrderHeader article.
               article1.ConnectionContext = conn;
               article1.Name = articleName1;
               article1.DatabaseName = publicationDbName;
               article1.SourceObjectName = articleName1;
               article1.SourceObjectOwner = schema;
               article1.PublicationName = publicationName;
               article1.Type = ArticleOptions.TableBased;

               // Set the required properties for the SalesOrderDetail article.
               article2.ConnectionContext = conn;
               article2.Name = articleName2;
               article2.DatabaseName = publicationDbName;
               article2.SourceObjectName = articleName2;
               article2.SourceObjectOwner = schema;
               article2.PublicationName = publicationName;
               article2.Type = ArticleOptions.TableBased;

               if (!article1.IsExistingObject) article1.Create();
               if (!article2.IsExistingObject) article2.Create();

               // Define a logical record relationship between 
               // PurchaseOrderHeader and PurchaseOrderDetail. 

               // Parent article.
               lr.JoinArticleName = articleName1;
               
               // Child article.
               lr.ArticleName = articleName2;
               lr.FilterName = lrName;
               lr.JoinUniqueKey = true;
               lr.FilterTypes = FilterTypes.LogicalRecordLink;
               lr.JoinFilterClause = lrClause;

               // Add the logical record definition to the parent article.
               article1.AddMergeJoinFilter(lr);
           }
           catch (Exception ex)
           {
               // Do error handling here and rollback the transaction.
               throw new ApplicationException(
                   "The filtered articles could not be created", ex);
           }
           finally
           {
               conn.Disconnect();
           }
' Define the Publisher and publication names.
Dim publisherName As String = publisherInstance
Dim publicationName As String = "AdvWorksSalesOrdersMerge"
Dim publicationDbName As String = "AdventureWorks2022"

' Specify article names.
Dim articleName1 As String = "SalesOrderHeader"
Dim articleName2 As String = "SalesOrderDetail"

' Specify logical record information.
Dim lrName As String = "SalesOrderHeader_SalesOrderDetail"
Dim lrClause As String = "[SalesOrderHeader].[SalesOrderID] = " _
        & "[SalesOrderDetail].[SalesOrderID]"

Dim schema As String = "Sales"

Dim article1 As MergeArticle = New MergeArticle()
Dim article2 As MergeArticle = New MergeArticle()
Dim lr As MergeJoinFilter = New MergeJoinFilter()
Dim publication As MergePublication = New MergePublication()

' Create a connection to the Publisher.
Dim conn As ServerConnection = New ServerConnection(publisherName)

Try
    ' Connect to the Publisher.
    conn.Connect()

    ' Verify that the publication uses precomputed partitions.
    publication.Name = publicationName
    publication.DatabaseName = publicationDbName
    publication.ConnectionContext = conn

    ' If we can't get the properties for this merge publication, then throw an application exception.
    If publication.LoadProperties() Then
        ' If precomputed partitions is disabled, enable it.
        If publication.PartitionGroupsOption = PartitionGroupsOption.False Then
            publication.PartitionGroupsOption = PartitionGroupsOption.True
        End If
    Else
        Throw New ApplicationException(String.Format( _
            "Settings could not be retrieved for the publication. " _
            & "Ensure that the publication {0} exists on {1}.", _
            publicationName, publisherName))
    End If

    ' Set the required properties for the SalesOrderHeader article.
    article1.ConnectionContext = conn
    article1.Name = articleName1
    article1.DatabaseName = publicationDbName
    article1.SourceObjectName = articleName1
    article1.SourceObjectOwner = schema
    article1.PublicationName = publicationName
    article1.Type = ArticleOptions.TableBased

    ' Set the required properties for the SalesOrderDetail article.
    article2.ConnectionContext = conn
    article2.Name = articleName2
    article2.DatabaseName = publicationDbName
    article2.SourceObjectName = articleName2
    article2.SourceObjectOwner = schema
    article2.PublicationName = publicationName
    article2.Type = ArticleOptions.TableBased

    If Not article1.IsExistingObject Then
        article1.Create()
    End If
    If Not article2.IsExistingObject Then
        article2.Create()
    End If

    ' Define a logical record relationship between 
    ' SalesOrderHeader and SalesOrderDetail. 

    ' Parent article.
    lr.JoinArticleName = articleName1
    ' Child article.
    lr.ArticleName = articleName2
    lr.FilterName = lrName
    lr.JoinUniqueKey = True
    lr.FilterTypes = FilterTypes.LogicalRecordLink
    lr.JoinFilterClause = lrClause

    ' Add the logical record definition to the parent article.
    article1.AddMergeJoinFilter(lr)
Catch ex As Exception
    ' Do error handling here and rollback the transaction.
    Throw New ApplicationException( _
            "The filtered articles could not be created", ex)
Finally
    conn.Disconnect()
End Try