在写入SQL Server 2014中的基础表后立即查询视图

时间:2015-08-13 23:05:07

标签: sql .net sql-server linq-to-sql

我遇到一个问题,如果我写一个表(使用Linq-to-SQL ),这是一个视图的依赖项,然后立即转身查询该视图以检查写入的影响(使用新的连接到数据库,因此新的数据上下文),写入的影响不会立即显示,但需要几秒钟才能显示。这种情况偶尔会发生(每10-20左右写10,000次左右。

这是视图的定义:

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
)

虽然这是由Linq-to-SQL生成的用于写入其中一个基础表的查询:

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)

这是Linq-to-SQL生成的用于检查写入效果的查询:

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]

此外,这是生成写入的Linq-to-SQL代码(使用F#类型提供程序):

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()

虽然这是生成读取的相应Linq-to-SQL:

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

我原以为System.Data.Linq.DataContext.SubmitChanges()只会在写事务完成后返回,并且视图的任何后续查询都必须包含写入的效果...我错过了什么/做错了什么?

3 个答案:

答案 0 :(得分:3)

我终于明白了这一点:数据库写入是在自己的线程中完成的,主线程在检查结果之前等待所有写线程完成。但是,代码中存在一个错误,它检查所有线程是否都已完成,导致主线程过早地进行检查。

答案 1 :(得分:0)

您的链接到SQL检查写入的效果是否可能正在查看旧的缓存数据?尝试使用上下文对象的refresh method预先刷新缓存。在对象上使用RefreshMode.OverwriteCurrentValues

答案 2 :(得分:0)

你可以试试table hints

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检查this博客条目,在我的情况下使用nolock提示解决问题。