我在一個asp.net web應用程序中使用db4o,正如您知道db4o何時返回它們未被排序的對象列表。阻止db4o在同一時間返回相同的對象
在我的網站上,我運行查詢並獲取結果中的最後一個對象並對其進行處理(某些處理,然後更新其中的一個字段)。
我的問題是,如果當我在那個對象上工作,如果另一個用戶到達並再次運行該查詢,同一個對象返回給他,並且兩個用戶都得到相同的對象。
我不想讓這種情況發生。我如何防止它發生?
我在一個asp.net web應用程序中使用db4o,正如您知道db4o何時返回它們未被排序的對象列表。阻止db4o在同一時間返回相同的對象
在我的網站上,我運行查詢並獲取結果中的最後一個對象並對其進行處理(某些處理,然後更新其中的一個字段)。
我的問題是,如果當我在那個對象上工作,如果另一個用戶到達並再次運行該查詢,同一個對象返回給他,並且兩個用戶都得到相同的對象。
我不想讓這種情況發生。我如何防止它發生?
不確定DB4O是否提供了這種開箱即用的東西,但可以自己實現某種悲觀鎖,從而使同一個對象不會被返回或將以只讀模式返回。您需要維護正在編輯的對象列表,並在每次返回對象時檢查此列表。但是之後會出現諸如用戶離開和對象陷入「編輯模式」等問題。您通常需要某種涉及超時機制的服務來處理該問題。它可能會變得複雜。或者樂觀地做它,例如,讓兩個用戶都編輯它,但只保存第一個用戶的更改,並在第二個用戶嘗試保存時給第二個用戶一個警告。通常用時間戳完成。
編輯
爲了提供一個具體的例子,此C#代碼提供到「鎖定」,從而它每次不帶回來的對象的基本方式。但在現實生活中,它會更復雜。
using System;
using System.Collections.Generic;
using System.Linq;
namespace ListTest
{
class Program
{
static void Main(string[] args)
{
DataAccess dataAccess = new DataAccess();
// get objects from database
List<MyThing> things = dataAccess.GetThings();
MyThing thingToWorkOn = things[things.Count-1];
printThingList(things);
// lock the object to work on
dataAccess.LockThing(thingToWorkOn);
// someone else gets the list - doesn't include thing being edited
List<MyThing> moreThings = dataAccess.GetThings();
printThingList(moreThings);
// edit the object
thingToWorkOn.Name = "Harrold";
thingToWorkOn.Name = "Harry";
// save the object and unlock it
dataAccess.Save(thingToWorkOn);
dataAccess.UnlockThing(thingToWorkOn);
// now when someone else gets the list, includes all objects
List<MyThing> evenMoreThings = dataAccess.GetThings();
printThingList(evenMoreThings);
}
static void printThingList(List<MyThing> things)
{
Console.WriteLine("* Things *");
things.ForEach(x => Console.WriteLine(x.Name));
Console.WriteLine();
}
}
// The objects you're working with. Could just use 'object' or some interface.
class MyThing : IEquatable<MyThing>
{
public string Name { get; set; }
public bool Equals(MyThing other)
{
return other.Name == this.Name;
}
}
// Class to get objects from database.
class DataAccess
{
// simple list to store 'locked' objects
private static List<MyThing> lockedThings = new List<MyThing>();
// Get all objects except the locked ones
public List<MyThing> GetThings()
{
List<MyThing> thingsFromDatabase = LoadThingsFromDatabase();
var nonLockedThings = (from thing in thingsFromDatabase
where !lockedThings.Contains(thing)
select thing
).ToList<MyThing>();
return nonLockedThings;
}
// lock an object so it can't be seen by anyone else
public void LockThing(MyThing thingToLock)
{
lockedThings.Add(thingToLock);
}
// unlock an object
public void UnlockThing(MyThing thingToLock)
{
lockedThings.Remove(thingToLock);
}
public void Save(MyThing thing)
{
// save to database
}
// dummy method to give us some objects
private List<MyThing> LoadThingsFromDatabase()
{
return new List<MyThing>() {
new MyThing(){ Name="Tom" },
new MyThing(){ Name="Dick" },
new MyThing(){ Name="Harry" }
};
}
}
}
您可以使用db4o內置的帶外消息傳遞支持來實現基本的鎖定系統。上面的Grant的列表可以在db4o服務器上實現。客戶端發送消息給服務器'我想編輯對象x',服務器試圖把對象放在列表中。如果成功,它會以'Yes,Go ahead'消息回覆,否則它可以回答'不,稍後再試'。當客戶端完成編輯時,它會向服務器發送一條消息,說'我已經完成了對象x'。
什麼是悲觀鎖? – iBoy 2010-08-12 10:18:39
這不是一個DB4O的事情,這是你必須對自己。這解釋了一點:http://www.agiledata.org/essays/concurrencyControl.html#PessimisticLocking。那篇文章是關於數據庫的,但無論如何也適用同樣的原則。 – 2010-08-12 10:48:57
基本上,當第一個用戶開始在一個對象上工作時,可以將它放在一個列表中,或許(在C#中)'列表