【发布时间】:2011-03-28 19:57:53
【问题描述】:
我在一个 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”,服务器尝试将对象放入其列表中。如果成功,它将回复“是,继续”消息,否则可以回复“否,稍后再试”。当客户端完成编辑后,它会向服务器发送一条消息说“我已经完成了对象 x”。
【讨论】: