2015-08-13 56 views
10

Ho un problema in cui se scrivo su una tabella (utilizzando Linq-to-SQL), che è una dipendenza di una vista, e quindi immediatamente svolta intorno e interrogare quella vista per verificare l'impatto della scrittura (usando una nuova connessione al DB, e quindi un nuovo contesto di dati), l'impatto della scrittura non appare immediatamente ma richiede alcuni secondi per apparire. Ciò accade solo occasionalmente (forse 10-20 volte per 10,000 o così scrive).Interrogazione di una vista immediatamente dopo la scrittura nelle tabelle sottostanti in SQL Server 2014

Questa è la definizione della vista:

CREATE VIEW [Position].[Transactions] 
WITH SCHEMABINDING 
AS 
(
    SELECT 
    Account, 
    Book, 
    TimeAPIClient AS DateTimeUtc, 
    BaseCcy AS Currency, 
    ISNULL(QuantityBase, 0) AS Quantity, 
    ValueDate AS SettleDate, 
    ISNULL(CAST(0 AS tinyint), 0) AS TransactionType 
    FROM Trades.FxSpotMF 
    WHERE IsCancelled = 0 

    UNION ALL 

    SELECT 
    Account, 
    Book, 
    TimeAPIClient AS DateTimeUtc, 
    QuoteCcy AS Currency, 
    ISNULL(-QuantityBase * Rate, 0) AS Quantity, 
    ValueDate AS SettleDate, 
    ISNULL(CAST(0 AS tinyint), 0) AS TransactionType 
    FROM Trades.FxSpotMF 
    WHERE IsCancelled = 0 

    UNION ALL 

    SELECT 
    Account, 
    Book, 
    ExecutionTimeUtc AS DateTimeUtc, 
    BaseCcy AS Currency, 
    ISNULL(QuantityBase, 0) AS Quantity, 
    ValueDate AS SettleDate, 
    ISNULL(CAST(1 AS tinyint), 1) AS TransactionType 
    FROM Trades.FxSpotManual 
    WHERE IsCancelled = 0 

    UNION ALL 

    SELECT 
    Account, 
    Book, 
    ExecutionTimeUtc AS DateTimeUtc, 
    QuoteCcy AS Currency, 
    ISNULL(-QuantityBase * Rate, 0) AS Quantity, 
    ValueDate AS SettleDate, 
    ISNULL(CAST(1 AS tinyint), 1) AS TransactionType 
    FROM Trades.FxSpotManual 
    WHERE IsCancelled = 0 

    UNION ALL 

    SELECT 
    Account, 
    Book, 
    ExecutionTimeUtc AS DateTimeUtc, 
    BaseCcy AS Currency, 
    ISNULL(SpotQuantityBase, 0) AS Quantity, 
    SpotValueDate AS SettleDate, 
    ISNULL(CAST(2 AS tinyint), 2) AS TransactionType 
    FROM Trades.FxSwap 

    UNION ALL 

    SELECT 
    Account, 
    Book, 
    ExecutionTimeUtc AS DateTimeUtc, 
    QuoteCcy AS Currency, 
    ISNULL(-SpotQuantityBase * SpotRate, 0) AS Quantity, 
    SpotValueDate AS SettleDate, 
    ISNULL(CAST(2 AS tinyint), 2) AS TransactionType 
    FROM Trades.FxSwap 

    UNION ALL 

    SELECT 
    Account, 
    Book, 
    ExecutionTimeUtc AS DateTimeUtc, 
    BaseCcy AS Currency, 
    ISNULL(ForwardQuantityBase, 0) AS Quantity, 
    ForwardValueDate AS SettleDate, 
    ISNULL(CAST(2 AS tinyint), 2) AS TransactionType 
    FROM Trades.FxSwap 

    UNION ALL 

    SELECT 
    Account, 
    Book, 
    ExecutionTimeUtc AS DateTimeUtc, 
    QuoteCcy AS Currency, 
    ISNULL(-ForwardQuantityBase * ForwardRate, 0) AS Quantity, 
    ForwardValueDate AS SettleDate, 
    ISNULL(CAST(2 AS tinyint), 2) AS TransactionType 
    FROM Trades.FxSwap 

    UNION ALL 

    SELECT 
    Account, 
    c.Book, 
    TimeUtc AS DateTimeUtc, 
    Currency, 
    ISNULL(Amount, 0) AS Quantity, 
    SettleDate, 
    ISNULL(CAST(3 AS tinyint), 3) AS TransactionType 
    FROM Trades.Commission c 
    JOIN Trades.Payment p 
    ON c.UniquePaymentId = p.UniquePaymentId 
    AND c.Book = p.Book 
) 

mentre questa è la query generata da Linq to SQL per scrivere una delle tabelle sottostanti:

INSERT INTO [Trades].[FxSpotMF] ([UniqueTradeId], [BaseCcy], [QuoteCcy], [ValueDate], [Rate], [QuantityBase], [Account], [Book], [CounterpartyId], [Counterparty], [ExTradeId], [TimeAPIClient], [TimeAPIServer], [TimeExchange], [TimeHandler], [UniqueOrderId], [IsCancelled], [ClientId], [SequenceId], [ExOrdId], [TradeDate], [OrderCycleId], [CycleIndex]) 
    VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10, @p11, @p12, @p13, @p14, @p15, @p16, @p17, @p18, @p19, @p20, @p21, @p22) 

e questo è la query generata da Linq to SQL per verificare l'effetto della scrittura:

SELECT 
    SUM([t0].[Quantity]) AS [Item2], 
    [t0].[Currency] AS [Item1] 
FROM [Position].[Transactions] AS [t0] 
WHERE ([t0].[Book] = @p0) 
AND ([t0].[DateTimeUtc] < @p1) 
GROUP BY [t0].[Currency] 

Inoltre, questa è la L INQ-to-SQL codice che genera la scrittura (utilizzando F provider # tipo):

type Schema = Microsoft.FSharp.Data.TypeProviders.DbmlFile<"TradeDb.dbml", ContextTypeName="TradeDb"> 

use db = new Schema.TradeDb(connectionString) 
let trade = new Schema.Trades_FxSpotMF() 
(* omitted: set object properties corresponding to column values here... *) 
db.Trades_FxSpotMF.InsertOnSubmit(trade) 
db.SubmitChanges() 

mentre questo è il corrispondente Linq to SQL che genera la lettura:

use db = new Schema.TradeDb(connectionString) 
query { for t in db.Position_Transactions do 
     where (t.Book = book && 
       t.DateTimeUtc < df.MaxExecutionTimeExcl 
      ) 
     groupBy t.Currency into group 
     let total = query { for x in group do sumBy x.Quantity } 
     select (group.Key, total) 
     } 
|> Map.ofSeq 

avrei pensato System.Data.Linq.DataContext.SubmitChanges() restituirebbe solo una volta completata la transazione di scrittura e che qualsiasi query successiva della vista deve contenere l'effetto della scrittura ... cosa mi manca/faccio male?

+0

Si prega di incollare il codice linq-to-sql? –

+0

Purtroppo non sono un guru di F # quindi sono un po 'perso qui.Proverò a chiamare il metodo dispose nel contesto db (un'istruzione using in C#) utilizzato per l'operazione di inserimento prima di chiamare la query select. La mia ipotesi è che l'esecuzione dell'istruzione di inserimento venga posticipata e talvolta l'istruzione select viene attivata prima che l'inserimento effettivo abbia luogo. –

+0

I due frammenti sopra riportati si trovano in due parti diverse del codice base, non eseguiti uno dopo l'altro. Inoltre, il contesto db è stato disposto per gentile concessione della sintassi 'use db ...'. Non penso che questo sia qualcosa di specifico di F #, questo è abbastanza comune Linq-to-SQL. – mpeac

risposta

3

Finalmente sono arrivato alla fine di questo: le scritture DB sono fatte nei loro thread, con il thread principale in attesa che tutti i thread di scrittura siano completati prima di controllare i risultati. Tuttavia, c'era un errore nel codice che controllava se tutti i thread erano completi, facendo sì che il thread principale facesse il check troppo presto.

-2

Si hanno creare una vista con rilegatura schema

CREATE VIEW [Position].[Transactions] 
WITH SCHEMABINDING 

ed ha il funzionamento 8 unione con 9 query da 4 tavoli

FROM Trades.FxSpotMF --2times 
    WHERE IsCancelled = 0 

FROM Trades.FxSpotManual --2 times 
    WHERE IsCancelled = 0 

FROM Trades.FxSwap -- 4 times 

FROM Trades.Commission c 
    JOIN Trades.Payment p 
    ON c.UniquePaymentId = p.UniquePaymentId 
    AND c.Book = p.Book 

per aggiornare la visualizzazione dopo ogni inserire in una di queste tabelle che il sistema potrebbe richiedere alcuni secondi e la query selezionata verrà eseguita immediatamente dopo l'inserimento. potrebbe accadere che l'inserimento avvenga entro 0 ~ 1 ms nella tabella, ma la visualizzazione di aggiornamento impiega più di 100 ms e seleziona la mancanza di query a causa della visualizzazione viene fornita dalla cache del server

+1

Ma pensavo che le viste non indicizzate fossero solo una query memorizzata, cioè, niente è memorizzato nella cache? Cioè, il risultato ottenuto dall'interrogazione di una vista è identico all'integrazione della definizione della vista nella tua query? E se la transazione di inserimento è completa, tutte le letture successive dovrebbero prendere il nuovo valore, giusto? O c'è qualche altro livello di caching che mi manca? – mpeac

+0

Potrebbe essere utile per spiegare- https://msdn.microsoft.com/en-us/library/cc293623.aspx?f=255&MSPPError=-2147217396 –

+0

Si tratta solo di nascondere il caching dei piani di esecuzione rispettati, non il caching di i risultati delle domande, non è vero? – mpeac

0

È possibile che il collegamento a SQL controllare l'effetto della scrittura sta guardando i vecchi dati memorizzati nella cache? Prova ad aggiornare preventivamente la cache con lo refresh method dell'oggetto contesto. Utilizzare RefreshMode.OverwriteCurrentValues sull'oggetto.

0

Potrebbe provare con table hints cioè

CREATE VIEW [Position].[Transactions] 
WITH SCHEMABINDING 
AS 
(
    SELECT 
    Account, 
    Book, 
    TimeAPIClient AS DateTimeUtc, 
    BaseCcy AS Currency, 
    ISNULL(QuantityBase, 0) AS Quantity, 
    ValueDate AS SettleDate, 
    ISNULL(CAST(0 AS tinyint), 0) AS TransactionType 
    FROM Trades.FxSpotMF WITH(NOLOCK) 
    WHERE IsCancelled = 0 

    UNION ALL 

    SELECT 
    Account, 
    Book, 
    TimeAPIClient AS DateTimeUtc, 
    QuoteCcy AS Currency, 
    ISNULL(-QuantityBase * Rate, 0) AS Quantity, 
    ValueDate AS SettleDate, 
    ISNULL(CAST(0 AS tinyint), 0) AS TransactionType 
    FROM Trades.FxSpotMF WITH(NOLOCK) 
    WHERE IsCancelled = 0 
    ... 
) 

Alos controllare this blog, nel mio caso utilizzare l'hint NOLOCK risolvere il problema.

+1

Quella voce del blog mostra che l'uso dell'hint NOLOCK potrebbe portare a file mancanti o letti due volte, il che è esattamente l'opposto di quello che sto cercando di ottenere. – mpeac

Problemi correlati