我有一個Web方法上傳事務(ASMX Web服務),它接受XML文件,驗證文件並將文件內容存儲在SQL Server數據庫中。我們注意到某些用戶可以同時提交兩次相同的文件。所以我們可以在我們的數據庫中再次使用相同的代碼(我們不能在數據庫上使用唯一索引,或者在數據庫級別執行任何操作,不要問我爲什麼)。我想我可以使用用戶ID字符串上的鎖定語句,但我不知道這是否會解決問題。或者如果我可以使用兌現對象來存儲所有用戶ID請求,並檢查是否有來自同一用戶ID的2個請求,我們將執行第一個請求並阻止第二個請求,並顯示錯誤消息 ,因此如果有人有任何想法,請幫助阻止來自同一用戶ID的多個請求到Web方法c#
1
A
回答
3
在字符串上阻塞是不好的。阻止你的網絡服務器是不好的。
AsyncLocker
是我寫的一個方便的類,它允許鎖定任何類型的行爲很好的字典中的鍵。它還需要異步進入臨界部(相對於鎖的正常封閉的行爲)之前等待:
public class AsyncLocker<T>
{
private LazyDictionary<T, SemaphoreSlim> semaphoreDictionary =
new LazyDictionary<T, SemaphoreSlim>();
public async Task<IDisposable> LockAsync(T key)
{
var semaphore = semaphoreDictionary.GetOrAdd(key,() => new SemaphoreSlim(1,1));
await semaphore.WaitAsync();
return new ActionDisposable(() => semaphore.Release());
}
}
這取決於以下兩個輔助類:
LazyDictionary:
public class LazyDictionary<TKey,TValue>
{
//here we use Lazy<TValue> as the value in the dictionary
//to guard against the fact the the initializer function
//in ConcurrentDictionary.AddOrGet *can*, under some conditions,
//run more than once per key, with the result of all but one of
//the runs being discarded.
//If this happens, only uninitialized
//Lazy values are discarded. Only the Lazy that actually
//made it into the dictionary is materialized by accessing
//its Value property.
private ConcurrentDictionary<TKey, Lazy<TValue>> dictionary =
new ConcurrentDictionary<TKey, Lazy<TValue>>();
public TValue GetOrAdd(TKey key, Func<TValue> valueGenerator)
{
var lazyValue = dictionary.GetOrAdd(key,
k => new Lazy<TValue>(valueGenerator));
return lazyValue.Value;
}
}
ActionDisposable:
public sealed class ActionDisposable:IDisposable
{
//useful for making arbitrary IDisposable instances
//that perform an Action when Dispose is called
//(after a using block, for instance)
private Action action;
public ActionDisposable(Action action)
{
this.action = action;
}
public void Dispose()
{
var action = this.action;
if(action != null)
{
action();
}
}
}
現在,如果你保持一個st這個地方的ATIC實例:
static AsyncLocker<string> userLock = new AsyncLocker<string>();
你可以用它在async
方法,利用LockAsync
的IDisposable
返回類型的美食寫一個using
聲明整齊地包裝了關鍵部分:
using(await userLock.LockAsync(userId))
{
//user with userId only allowed in this section
//one at a time.
}
如果我們在進入之前需要等待,它會異步完成,釋放線程來處理其他請求,而不是阻塞,直到等待結束,並且可能在加載時混亂服務器的性能。
當然,當你需要擴展到多個web服務器時,這種方法將不再起作用,並且你需要使用不同的方法(可能通過數據庫)進行同步。
相關問題
- 1. 如何阻止來自同一IP的多個請求
- 2. Web服務和來自同一客戶端的多個請求
- 3. 阻止來自同一服務器會話的相同請求
- 4. PHP cURL - 來自同一個'用戶'的多個請求
- 5. Apache阻止多個請求?
- 6. PHP web-app deamon處理來自同一用戶的多個請求
- 7. 來自域的阻止請求
- 8. 如何阻止用戶查看來自AJAX請求的響應?
- 9. WCF來自同一客戶端的多個請求
- 10. POST請求 - 跨來源請求阻止
- 11. phpbb3如何阻止來自不同地方的同一用戶登錄
- 12. 阻止請求
- 13. Nodejs一個請求阻止另一個請求
- 14. 一個有效的方法來阻止一個具體的網站發出POST請求到您的服務器?
- 15. Heroku阻止請求到URL
- 16. IIS7上的FastCGI ...來自同一用戶會話的多個併發請求?
- 17. 發送一個POST請求到一個來自C#的URL請求#
- 18. Windows手機8異步Web請求與阻止用戶觸摸
- 19. 如何獲得來自同一控制器的多個Web服務請求?
- 20. 改裝call.enqueue阻止第一個請求
- 21. 防止來自同一用戶名的多個連接
- 22. 如何阻止多個用戶在PHP中同時訪問單一方法?
- 23. 排隊來自同一個HTTP客戶端的servlet請求?
- 24. 阻止2個用戶登錄到同一個帳戶
- 25. 同步來自多臺機器的外部Web請求
- 26. 來自用戶的每個請求調用一個新的getConnection()?
- 27. PHP - 阻止來自用戶的
- 28. Servlet請求阻止
- 29. 如何阻止來自web瀏覽器和cURL等工具的請求?
- 30. 來自同一分支的多個請求
內容是否完全重複?是否允許重複?如果不是,您可以簡單地丟棄重複請求(如果他們提交內容兩次,但_far_足以避免鎖定) –
切勿鎖定字符串。永遠。真。 http://stackoverflow.com/questions/12804879/is-it-ok-to-use-a-string-as-a-lock-object – spender