2010-08-12 82 views
1

我在一個asp.net web應用程序中使用db4o,正如您知道db4o何時返回它們未被排序的對象列表。阻止db4o在同一時間返回相同的對象

在我的網站上,我運行查詢並獲取結果中的最後一個對象並對其進行處理(某些處理,然後更新其中的一個字段)。

我的問題是,如果當我在那個對象上工作,如果另一個用戶到達並再次運行該查詢,同一個對象返回給他,並且兩個用戶都得到相同的對象。

我不想讓這種情況發生。我如何防止它發生?

回答

1

不確定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" } 
      }; 
     } 
    } 
} 
+0

什麼是悲觀鎖? – iBoy 2010-08-12 10:18:39

+1

這不是一個DB4O的事情,這是你必須對自己。這解釋了一點:http://www.agiledata.org/essays/concurrencyControl.html#PessimisticLocking。那篇文章是關於數據庫的,但無論如何也適用同樣的原則。 – 2010-08-12 10:48:57

+0

基本上,當第一個用戶開始在一個對象上工作時,可以將它放在一個列表中,或許(在C#中)'列表 LockedObjects'。當其他人想要使用某個對象時,請檢查它是否在該列表中 - 如果是,則不允許使用該對象,或者只能讀取而不更新它。當第一個人完成編輯時,該對象將從該列表中刪除。 – 2010-08-12 10:51:13

0

您可以使用db4o內置的帶外消息傳遞支持來實現基本的鎖定系統。上面的Grant的列表可以在db4o服務器上實現。客戶端發送消息給服務器'我想編輯對象x',服務器試圖把對象放在列表中。如果成功,它會以'Yes,Go ahead'消息回覆,否則它可以回答'不,稍後再試'。當客戶端完成編輯時,它會向服務器發送一條消息,說'我已經完成了對象x'。

相關問題