Insert And Remove

When an object is inserted or removed from the list, only the list object needs to be updated, the objects in the list are not going to be changed. That means that for the object from the previous topic we will need to set update depth = 1.

Let's fill up the database with 2 long lists of objects:

ListOperationsExample.cs: FillUpDb
01private static void FillUpDb() 02 { 03 int listCount = 2; 04 int dataCount = 50000; 05 Stopwatch sw = new Stopwatch(); 06 File.Delete(DbFile); 07 IObjectContainer db = Db4oFactory.OpenFile(DbFile); 08 try 09 { 10 sw.Start(); 11 12 for (int i = 0; i < listCount; i++) 13 { 14 ListObject lo = new ListObject(); 15 lo.Name = "list" + i.ToString("00"); 16 for (int j = 0; j < dataCount; j++) 17 { 18 DataObject dataObject = new DataObject(); 19 dataObject.Name = "data" + j.ToString("00000"); 20 dataObject.Data = DateTime.Now.ToString() + " ---- Data Object " + j.ToString("00000"); 21 lo.Data.Add(dataObject); 22 } 23 db.Set(lo); 24 } 25 sw.Stop(); 26 } 27 finally 28 { 29 db.Close(); 30 } 31 Console.WriteLine("Completed {0} lists of {1} objects each.", listCount, dataCount); 32 Console.WriteLine("Elapsed time: {0}", sw.Elapsed.ToString()); 33 }
ListOperationsExample.vb: FillUpDb
01Private Shared Sub FillUpDb() 02 Dim listCount As Integer = 2 03 Dim dataCount As Integer = 50000 04 Dim sw As Stopwatch = New Stopwatch 05 File.Delete(DbFile) 06 Dim db As IObjectContainer = Db4oFactory.OpenFile(DbFile) 07 Try 08 sw.Start() 09 Dim i As Integer = 0 10 While i < listCount 11 Dim lo As ListObject = New ListObject 12 lo.Name = "list" + i.ToString("00") 13 Dim j As Integer = 0 14 While j < dataCount 15 Dim dataObject As DataObject = New DataObject 16 dataObject.Name = "data" + j.ToString("00000") 17 dataObject.Data = DateTime.Now.ToString + " ---- Data Object " + j.ToString("00000") 18 lo.Data.Add(dataObject) 19 System.Math.Min(System.Threading.Interlocked.Increment(j), j - 1) 20 End While 21 db.Set(lo) 22 System.Math.Min(System.Threading.Interlocked.Increment(i), i - 1) 23 End While 24 sw.Stop() 25 Finally 26 db.Close() 27 End Try 28 Console.WriteLine("Completed {0} lists of {1} objects each.", listCount, dataCount) 29 Console.WriteLine("Elapsed time: {0}", sw.Elapsed.ToString) 30 End Sub

We will remove an object from one list and insert it into another:

ListOperationsExample.cs: RemoveInsert
01private static void RemoveInsert() 02 { 03 Stopwatch sw = new Stopwatch(); 04 05 IObjectContainer db = Db4oFactory.OpenFile(DbFile); 06 try 07 { 08 // set activation depth to 1 for the quickest execution 09 db.Ext().Configure().UpdateDepth(1); 10 IList<ListObject> result = db.Query<ListObject>(); 11 if (result.Count == 2) 12 { 13 // retrieve 2 ListObjects 14 ListObject lo1 = result[0]; 15 ListObject lo2 = result[1]; 16 DataObject dataObject = lo1.Data[0]; 17 // move the first object from the first 18 // ListObject to the second ListObject 19 lo1.Data.Remove(dataObject); 20 lo2.Data.Add(dataObject); 21 22 Console.WriteLine("Removed from the first list, count is {0}, setting data...", lo1.Data.Count); 23 Console.WriteLine("Added to the second list, count is {0}, setting data...", lo2.Data.Count); 24 sw.Start(); 25 db.Set(lo1); 26 db.Set(lo2); 27 db.Commit(); 28 sw.Stop(); 29 } 30 } 31 finally 32 { 33 db.Close(); 34 } 35 Console.WriteLine("Storing took {0}", sw.Elapsed.ToString()); 36 }
ListOperationsExample.vb: RemoveInsert
01Private Shared Sub RemoveInsert() 02 Dim sw As Stopwatch = New Stopwatch 03 Dim db As IObjectContainer = Db4oFactory.OpenFile(DbFile) 04 Try 05 ' set activation depth to 1 for the quickest execution 06 db.Ext.Configure.UpdateDepth(1) 07 Dim result As IList(Of ListObject) = db.Query(Of ListObject)() 08 If result.Count = 2 Then 09 ' retrieve 2 ListObjects 10 Dim lo1 As ListObject = result(0) 11 Dim lo2 As ListObject = result(1) 12 Dim dataObject As DataObject = lo1.Data(0) 13 ' move the first object from the first 14 ' ListObject to the second ListObject 15 lo1.Data.Remove(dataObject) 16 lo2.Data.Add(dataObject) 17 Console.WriteLine("Removed from the first list, count is {0}, setting data...", lo1.Data.Count) 18 Console.WriteLine("Added to the second list, count is {0}, setting data...", lo2.Data.Count) 19 sw.Start() 20 db.Set(lo1) 21 db.Set(lo2) 22 db.Commit() 23 sw.Stop() 24 End If 25 Finally 26 db.Close() 27 End Try 28 Console.WriteLine("Storing took {0}", sw.Elapsed.ToString) 29 End Sub

Remember, if an object is removed from the list and is not going to be used any more, it should be deleted manually:

db.Delete(dataObject)

Let's check if the results are correct:

ListOperationsExample.cs: CheckResults
01private static void CheckResults() 02 { 03 Stopwatch sw = new Stopwatch(); 04 IObjectContainer db = Db4oFactory.OpenFile(DbFile); 05 try 06 { 07 IList<ListObject> result = db.Query<ListObject>(); 08 if (result.Count > 0) 09 { 10 // activation depth should be enough to activate 11 // ListObject, DataObject and its list members 12 int activationDepth = 3; 13 db.Ext().Configure().ActivationDepth(activationDepth); 14 Console.WriteLine("Result count was {0}, looping with activation depth {1}", result.Count, activationDepth); 15 sw.Start(); 16 foreach (ListObject lo in result) 17 { 18 Console.WriteLine("ListObj {0} has {1} objects", lo.Name, 19 ((lo.Data == null) ? "<null>" : lo.Data.Count.ToString())); 20 Console.WriteLine(" --- {0} at index 0", 21 ((lo.Data != null && lo.Data.Count > 0) ? lo.Data[0].ToString() : "<null>")); 22 } 23 sw.Stop(); 24 } 25 } 26 finally 27 { 28 db.Close(); 29 } 30 Console.WriteLine("Activation took {0}", sw.Elapsed.ToString()); 31 }
ListOperationsExample.vb: CheckResults
01Private Shared Sub CheckResults() 02 Dim sw As Stopwatch = New Stopwatch 03 Dim db As IObjectContainer = Db4oFactory.OpenFile(DbFile) 04 Try 05 Dim result As IList(Of ListObject) = db.Query(Of ListObject)() 06 If result.Count > 0 Then 07 ' activation depth should be enough to activate 08 ' ListObject, DataObject and its list members 09 Dim activationDepth As Integer = 3 10 db.Ext.Configure.ActivationDepth(activationDepth) 11 Console.WriteLine("Result count was {0}, looping with activation depth {1}", result.Count, activationDepth) 12 sw.Start() 13 For Each lo As ListObject In result 14 Console.WriteLine("ListObj {0} has {1} objects", lo.Name, (Microsoft.VisualBasic.IIf((lo.Data Is Nothing), "<null>", lo.Data.Count.ToString))) 15 Console.WriteLine(" --- {0} at index 0", (Microsoft.VisualBasic.IIf((Not (lo.Data Is Nothing) AndAlso lo.Data.Count > 0), lo.Data(0).ToString, "<null>"))) 16 Next 17 sw.Stop() 18 End If 19 Finally 20 db.Close() 21 End Try 22 Console.WriteLine("Activation took {0}", sw.Elapsed.ToString) 23 End Sub

You will see that insert/remove operation takes much less time with the correct update depth setting.