【发布时间】:2015-08-13 23:05:07
【问题描述】:
我遇到了一个问题,如果我写入一个依赖于视图的表(使用 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() 只会在写入事务完成后返回,并且视图的任何后续查询都必须包含写入的效果......我错过了什么/做错了什么?
【问题讨论】:
-
你能粘贴你的 linq-to-sql 代码吗?
-
不幸的是,我不是 F# 大师,所以我有点迷路了。在调用 select 查询之前,我会尝试在用于插入操作的 db 上下文(c# 中的 using 语句)上调用 dispose 方法。我的猜测是插入语句的执行被延迟,有时 select 语句在实际插入发生之前被触发。
-
上面的两个sn-ps位于代码库的两个不同部分,没有一个接一个地执行。此外,db 上下文已通过“use db...”语法进行处理。我不认为这是 F# 特有的,这是相当普通的 Linq-to-SQL。
-
好吧,我从未使用过 F#,但很明显,当您尝试读回数据时,写入事务尚未提交。所以,我会检查
SubmitChanges上的文档并验证它何时以及如何提交事务。默认情况下,它可能取决于垃圾收集器。因此,框架中必须有一个方法可以用来显式启动和提交事务,而无需等待垃圾收集器启动, -
我认为使用 sql server profiler 查看发生了什么会更好。每个事务什么时候开始,什么时候结束,等等。
标签: sql .net sql-server linq-to-sql