代码之家  ›  专栏  ›  技术社区  ›  iBoy

在db4o中防止同一对象同时返回

  •  1
  • iBoy  · 技术社区  · 14 年前

    我在一个应用程序中使用db4oasp.net web应用程序,如您所知,当db4o返回一个对象列表时,它们没有排序。

    在我的网站中,我运行一个查询,得到结果中的最后一个对象,并对其进行处理(一些处理,然后更新其中一个字段)。

    我不想让这种事发生。我怎样才能防止它发生?

    2 回复  |  直到 14 年前
        1
  •  1
  •   Grant Crofton    14 年前

    不确定DB4O是否提供了这种现成的功能,但是可以自己实现某种悲观锁,这样同一个对象要么不会返回,要么以只读模式返回。您需要维护一个正在编辑的对象列表,并在每次返回对象时检查该列表。但是也有一些问题,比如用户离开,对象被卡在“编辑模式”中等等。你通常需要一种包含超时机制的服务来处理这个问题。事情可能会变得复杂。

    编辑

    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" }
                };
            }
        }
    }
    
        2
  •  0
  •   Ants    14 年前

    您可以使用db4o内置的带外消息传递支持来实现基本的锁定系统。上面的Grant列表可以在db4o服务器上实现。客户端向服务器发送消息“我要编辑对象x”,服务器尝试将对象放入其列表中。如果成功,它将用“是,继续”消息答复,否则它可以用“否,稍后再试”消息答复。当客户端完成编辑后,它会向服务器发送一条消息,说“我已经完成了对象x”。