にC#の同期ロジックを以下の...私はEntity Frameworkのロジックを以下している、と私は、ストアドプロシージャに変換したい、私はストアドプロシージャで排他ロックを使用してみましたが、それはタイムアウトの多くにつながるストアドプロシージャ
を翻訳4列
Pages
PageID
SpaceAvailable
SpaceOccupied
TotalSpace
を持っているハードディスクのいくつかの並べ替えとしてページを考えるとスペースが利用可能であるように私は、オブジェクトが収まらない場合、それは次の使用可能なページを取得します、ページに私のオブジェクトを割り当てる必要があります。
後
// a static lock to prevent race condition
static object Locker = new Object();
long AllocateNewPage(MyContext context, int requestedSize){
long pageID = 0;
// what is T-SQL lock equaivalent?
lock(Locker){
using(TransactionScope scope = new TransactionScope()){
var page = context.Pages
.Where(x=>x.SpaceAvailable>requestedSize)
.OrderBy(x=>x.PageID)
.First();
page.SpaceOccupied = page.SpaceOccupied + requestedSize;
page.SpaceAvailable = page.SpaceAvailable - requestedSize;
context.SaveChanges();
scope.Commit();
pageID = page.PageID;
}
}
return pageID;
}
は私が書かれているストアドプロシージャているが、私は他に同じことをC#で正しく、非常に高速に実行タイムアウト、5秒に設定しているとして、それはタイムアウトがたくさんになり、唯一の問題は、ある私がする必要はありデータベースを複数のクライアントに提供するように、これをストアドプロシージャに移動します。
CREATE procedure [GetPageID]
(
@SpaceRequested int
)
AS
BEGIN
DECLARE @DBID int
DECLARE @lock int
DECLARE @LockName varchar(20)
SET @LockName = 'PageLock'
BEGIN TRANSACTION
-- acquire a lock
EXEC @lock = sp_getapplock
@Resource = @LockName,
@LockMode = 'Exclusive',
@LockTimeout = 5000
IF @lock<>0 BEGIN
ROLLBACK TRANSACTION
SET @DBID = -1
SELECT @DBID
return 0
END
SET @DBID = coalesce((SELECT TOP 1 PageID
FROM Pages
WHERE SpaceAvailable > @SpaceRequested
ORDER BY PageID ASC),0)
UPDATE Pages SET
SpaceAvailable = SpaceAvailable - @SpaceRequested,
SpaceOccupied = SpaceOccupied + @SpaceRequested
WHERE PageID = @DBID
EXEC @lock = sp_releaseapplock @Resource = @LockName
COMMIT TRANSACTION
SELECT @DBID
END
私は、ストアドプロシージャについて多くを知らないが、ないページを埋める上できなくなりますように、私はロックモードでページを割り当てる必要があります。
AM私は思慮深いですか? トランザクションで実行していてもロックが必要ですか?
あなたの答えをありがとう、なぜ私の現在のロジックを変更した、それは間違っていたと思いますか?私はSPの専門家ではないので、私は好奇心から尋ねるだけです。あなたは選択と更新の両方を1つのステートメントで行うように見えますか? –
私はロジックを変更していない、私は実装を変更しました。あなたは多くの不必要なことをしている、これらは削除されました。唯一の選択は '@ res'テーブルからのものですが、update文は何も選択しませんが、ページIDを返します。これを書いたので、私は単に一時テーブルなしでクライアントに出力することができたことに気付きました。 – GSerg
これはまた、TransactionScope内で同じロジックをカプセル化している場合、ストアドプロシージャが必要ないことを意味しますか? –