Welcome to Sign in | Help
in Search

Merge replication, join filter pe relatii m:n

Last post 07-16-2008, 12:09 AM by Cryogenic1981. 11 replies.
Sort Posts: Previous Next
  •  07-08-2008, 11:04 AM 5288

    Merge replication, join filter pe relatii m:n


    Am urmatoare problema,

    trebuie sa filtrez dinamic o replica in SQL Server 2005 cu subscriptii SQL Compact 3.5 si am urmatorul scenariu, o tabela Company si o tabela CompanyRelations care e folosita pentru a crea relatii m:n intre comapanii:

    Table : [Company] ( IDCompany PK identity, <restul coloanelor ...>)
    Table:  [CompanyRelations] (CompanyID FK references IDCompany , CompanyRefID FK references IDCompany,<restul coloanelor ...>)

    Deci tabela CompanyRelations are 2 FK-uri spre tabela Company, iar eu trebuie sa folosesc un join filter pentru a filtra tabela CompanyRelations in functie de tabela Company.

    Ce se intampla in cazul meu:

    Am de ex urmatoarele date:

    [Company]

    ID, Name
    1   Company1
    2   Company2
    3   Company3

    [CompanyRelations]

    CompanyID, CompanyRefID
    1  2
    1  3

    Daca tabela Company e filtrata pernu ID-urile 1 si 2 iar join filtrer e  [Company].[IDCompany] = [CompanyRef].[CompanyID]

    atunci prin join filter se filtreaza row-urile (1 2) si (1 3) din CompanyRelations. Row-ul (1 3) va ajunge pe subscriber fara ca sa existe compania cu ID 3 si de aici sincronizarea da o eroare de referential integrity la insert.

    Eu trebuie sa filtrez tabela CompanyRelations astfel incat sa contina row-uri ce fac referire la companiiile filtrate prin ambele foreign key-uri. insa un join filter nu ma lasa sa spefifit decat clauza de join adica ce vine dupa Join [table] ON ...

    As aprecia daca ar putea cineva sa-mi dea un hint cum as putea sa filtrez o tabela de relatii m:n pentru merge replication in functie de alta tabela.

               Mersi,
                        Cata

  •  07-08-2008, 11:46 AM 5289 in reply to 5288

    Re: Merge replication, join filter pe relatii m:n

    Dar WHERE  (dbo.CompanyRelations.CompanyRefID IN (1, 2)) AND (dbo.CompanyRelations.CompanyID IN (1, 2))  ca si conditie de filtrare n-ar merge ?

    Adica sa pui filtru pe ambele chei si in felul acesta n-ar mai aparea compania cu id-ul 3


    Gheorghe Ciubuc,SQL Server Influencer, MCP(SQL 2000), MCTS (SQL Server 2005) , OCA(Oracle 9i), Sybase(Brainbench)
  •  07-09-2008, 11:10 AM 5293 in reply to 5289

    Re: Merge replication, join filter pe relatii m:n

    Pai trebuie sa filtrez tabela CompanyRelations in functie de tabela Company care e filtrata dinamic, adica nu pot pune conditii de genul IN (1,2) pentru ca aste e filtrare statica.

    Aici s-ar putea folosi o table valued function care sa intoarca o lista de ID-uri de Company, insa e o problema daca fac asa, adica la prima sincronizare totul merge ok, dar cand se shimba filtrul pe tabela Company (nu se sqhimba query-ul ci se doar se filtreaza diferit in functie de context), tabela CompanyRelations nu se mai filtreaza, ramane cu acelasi filtru.



  •  07-11-2008, 2:47 PM 5303 in reply to 5293

    Re: Merge replication, join filter pe relatii m:n

    Cryogenic1981:
    Pai trebuie sa filtrez tabela CompanyRelations in functie de tabela Company care e filtrata dinamic, adica nu pot pune conditii de genul IN (1,2) pentru ca aste e filtrare statica.

    Aici s-ar putea folosi o table valued function care sa intoarca o lista de ID-uri de Company, insa e o problema daca fac asa, adica la prima sincronizare totul merge ok, dar cand se shimba filtrul pe tabela Company (nu se sqhimba query-ul ci se doar se filtreaza diferit in functie de context), tabela CompanyRelations nu se mai filtreaza, ramane cu acelasi filtru.


    Încearcă să indici faptul că funcţia respectivă este nondeterministă inserând în codul sursă al acesteia, apelul unei functii nondeterministe sistem cum ar fi GETDATE().

    Dacă foloseşti acea funcţie care returnează o tabelă, încearcă să modifici tipul joncţiunii în CROSS/OUTER APPLY:
    CREATE FUNCTION FunctiaPestelui(@p TINYINT)
    RETURNS TABLE
      RETURN ( SELECT POWER(10,@p) AS ID )
    GO

    SELECT *
    INTO TabelaPestelui
    FROM
      (
      SELECT 10 AS ID,'B' AS Nume,1 AS Nr
      UNION
      SELECT 100,    'C',    2
      UNION
      SELECT 3333,  'D',    3
      UNION
      SELECT 10000,  'E',    4
      UNION
      SELECT 555555,  'F',    5
      ) AS Sursa

    --OK
    SELECT *
    FROM TabelaPestelui AS TP
      CROSS APPLY dbo.FunctiaPestelui(TP.Nr) AS T2
    WHERE TP.ID = T2.ID

    --Eroare
    SELECT *
    FROM TabelaPestelui AS TP
      INNER JOIN dbo.FunctiaPestelui(TP.Nr) AS T2
    ON TP.ID = T2.ID

  •  07-13-2008, 11:27 PM 5310 in reply to 5303

    Re: Merge replication, join filter pe relatii m:n

    join filtrer e
    [Company].[IDCompany] = [CompanyRef].[CompanyID]
    OR
    [Company].[IDCompany] = [CompanyRef].[CompanyRefID]

    ?
  •  07-14-2008, 12:57 PM 5311 in reply to 5303

    Re: Merge replication, join filter pe relatii m:n

    Nu pot folosi CROSS APPLY intr-un filtru join de "merge replication".

    Eu trebuie sa dau ce urmeaza dupa "SELECT <replicated fields> FROM [ParentTable]
    INNER JOIN [ChildTable] ON", doar de aici inainte pot scrie clauza de join, nu pot shimba join-ul respectiv in outer join sau cross apply sau alt tip de join, pentru ca SQL serverul creaza pana la acel  punct selectul si concateneaza conditia de join care o specific eu.

    Mai specific, un join filter se creaza in felul urmator, exemplu din MSDN :

    -- Add a merge join filter between SalesOrderHeader and SalesOrderDetail.
    EXEC sp_addmergefilter
    @publication = @publication,
    @article = @table3,
    @filtername = N'SalesOrderDetail_SalesOrderHeader',
    @join_articlename = @table2,
    @join_filterclause = N'SalesOrderHeader.SalesOrderID = SalesOrderDetail.SalesOrderID',
    @join_unique_key = 1,
    @filter_type = 1,
    @force_invalidate_snapshot = 1,
    @force_reinit_subscription = 1;
    GO



  •  07-14-2008, 1:04 PM 5312 in reply to 5310

    Re: Merge replication, join filter pe relatii m:n

    B_gd_n[ ]Sahlean:
    join filtrer e
    [Company].[IDCompany] = [CompanyRef].[CompanyID]
    OR
    [Company].[IDCompany] = [CompanyRef].[CompanyRefID]

    ?


    Daca creez in acest fell filtrul, tabela [CompanyRelation] filtrata v-a contine row-uri cu FK-uri spre tabela [Company] care nu exista pe client. iti dau un exemplu:

    in tabela Company:

    ID, Name
    1   Company1
    2   Company2
    3  Company 3

    iar in tabela CompanyRelation urmatoarele row-uri:
    CompanyID, CompanyRefID
    1                 2
    1                 3


    Daca tabela Company e filtrata dinamic asfel incat sa se replice Companiile cu ID 1 si 2, filtrul de join va face sa se replice si row-ul (1, 3), iar pe client v-a aparea o eroare de integritate referentiala, adica se v-a incerca inserarea uneii liniii in CompanyRelation cu FK = 3, iar row-ul din Company cu ID = 3 nu exista.


  •  07-15-2008, 11:27 AM 5313 in reply to 5293

    Re: Merge replication, join filter pe relatii m:n

    Cryogenic1981:
    ...
    Aici s-ar putea folosi o table valued function care sa intoarca o lista de ID-uri de Company, insa e o problema daca fac asa, adica la prima sincronizare totul merge ok, dar cand se shimba filtrul pe tabela Company (nu se sqhimba query-ul ci se doar se filtreaza diferit in functie de context), tabela CompanyRelations nu se mai filtreaza, ramane cu acelasi filtru.
    ...

    Trebuie initializata din nou subscriptia si apoi lansezi sincronizarea.


  •  07-15-2008, 12:45 PM 5314 in reply to 5313

    Re: Merge replication, join filter pe relatii m:n

    B_gd_n[ ]Sahlean:
    Cryogenic1981:
    ...
    Aici s-ar putea folosi o table valued function care sa intoarca o lista de ID-uri de Company, insa e o problema daca fac asa, adica la prima sincronizare totul merge ok, dar cand se shimba filtrul pe tabela Company (nu se sqhimba query-ul ci se doar se filtreaza diferit in functie de context), tabela CompanyRelations nu se mai filtreaza, ramane cu acelasi filtru.
    ...

    Trebuie initializata din nou subscriptia si apoi lansezi sincronizarea.




    Din pacate asta nu e o solutie pentru ca initializarea subscriptiei + transferul snapshot-ului dureaza minute bune, (10+) prin gprs. Filtrarea a fost creata pentru ca volumul de date la client e foarte mare fara nici un filtru aplicat (Problema de de spatiu pe pocket PC), dar si timpul in care se efectueaza o sincronizare e important. (Fara reinitializarea subscriptiei, timpul de sincronizare e de cateva secunde (10-20), pentru ca se transfera doar row-urile "delta" intre publisher si subscriber).

    Solutia actuala e una care nu-mi place foarte mult, dar functioneaza, si anume daca se filtrezz tabela Company in functie de anumite ID-uri, se includ automat si ID-urile de companie care au relatie intre ele.

    De ex daca exista urmatoarele row-uri:

    [Company]                                              [CompanyRelation]
    ID, CompanyName                                   CompanyID, CompanyRefID
    1   Company1                                          1                 3
    2   Company2
    3   Company3

    iar filtrul trebuie pus pe Compania cu ID = 1, se adauga automat in filtru si compania cu ID = 3, astfel incat atunci cand se replica row-ul (1,3) din CompanyRelation sa nu apara eroare de integritate referentiala, insa in acest fell am dus date in plus pe client (inutile).







  •  07-15-2008, 1:12 PM 5315 in reply to 5314

    Re: Merge replication, join filter pe relatii m:n

    [1] Aplicaţia care ruleaza pe Pocket PC modifică datele din Company şi CompanyRelations în sensul că modifică/şterge înregistrările copiate de la Publisher ?
    Dacă nu, atunci poţi încerca să implementezi o procedură stocată care să realizeze sincronizare. În plus va fi (mai mult ca sigur) mai rapidă decât ce ofera SQL Server.

    /

    [2] Cum ai definit filtrul "... filtrul trebuie pus pe Compania cu ID = 1, se adauga automat in filtru si compania cu ID = 3 ..." ?
    Filtrul e definit pe Company sau/şi pe CompanyRelation ?
  •  07-15-2008, 7:15 PM 5323 in reply to 5315

    Re: Merge replication, join filter pe relatii m:n

    O soluţie inspirată de MSDN ar fi:
    [1] creezi o tabela Parametru cu un singur câmp ID care este şi cheie primară. Aici inserezi ID-uri în funcţie care care se va realiza filtrare
    [2] în tabela CompanyRelation se adaugă un câmp Replicate de tip bit
    [3] în Publication se adaugă la "Filter Rows" condiţia Replicate = 1
    [4] în job-ul tip REPL-merge  adaugi  o etapă (step) tip "T-SQL Script" înainte de etapa "Run Agent"

    [5] inserezi codurile în funcţie de care se doreşte filtrarea la "Merge Replication" şi lansezi sincronizarea

    Tehnica se poate aplica cu mici variaţiuni şi pe tabela Company.
  •  07-16-2008, 12:09 AM 5324 in reply to 5323

    Re: Merge replication, join filter pe relatii m:n

    Da, asa functioneaza filtrarea pe primul nivel, insa nivelurile urmatoare sunt filtrade de tabelele de prim nivel prin join filter.
View as RSS news feed in XML
Powered by Community Server (Commercial Edition), by Telligent Systems