VelocityDB & VelocityGraph

Object and Graph Database - ask us, share & let us know what you need.

Reference to object without opening

How can I add a reference to an object, if I know its oid, and I don't want to open it?

If I just do :

var referenceToObj = new EntityObject{ID = knownOID}
var newObj = new AnotherObject(referenceToObj);
session.Persist(newObj);

than both newObj is created and new object referenceToObj is created (and it is not desired). I think, that API ignores its ID property and looks at IsPersistent which returns false;

Descending sort in the Index field attribute

Can you add the possibility to set descending sort  while using Index Attribute on the field? Something like [Index(descendingSort:true)]

As far I know, it is  possible to use descending sort with attribute on the class by prepending a minus, i.e. [Index("-indexField")]

Issues with AllObjects<T> and UpdateTypeVersion

1) If I just call session.AllObjects<T> , I get an exception

Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.
[ReflectionTypeLoadException: Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.]
   System.Reflection.RuntimeModule.GetTypes(RuntimeModule module) +0
   System.Reflection.RuntimeModule.GetTypes() +9
   System.Reflection.Assembly.GetTypes() +143
   VelocityDb.OfType.a(Assembly A_0) +14
   System.Linq.<SelectManyIterator>d__31`3.MoveNext() +267
   System.Linq.WhereSelectEnumerableIterator`2.MoveNext() +165
   VelocityDb.OfType.a(SessionBase A_0) +904
   VelocityDb.b.v() +1050
   VelocityDb.a.g() +221

But when I use session.AllObjects<T>(false), there is no such exception. I don't know is it a bug or not.


2) I need to update class with already persisted objects before after adding another indexable value (i.e.[Index]private string _anotherIndex ), but I cannot.

There is an exception (I've tried session.UpdateClass in different places)

Line 23:                 session.UpdateClass(typeof(DomainObject));
Line 24: foreach(var o in session.AllObjects<DomainObject>(false)) Line 25: o.UpdateTypeVersion(); Line 26: Line 27: session.Commit();


Source File: --

Stack Trace: 

[ArgumentOutOfRangeException: Index and count must refer to a location within the buffer.
Parameter name: bytes]
   System.Text.UTF8Encoding.GetString(Byte[] bytes, Int32 index, Int32 count) +14309108
   VelocityDb.TypeInfo.DataMember.DecodeToString(Byte[] member, Int32& offset, Int32 numberOfBytes) +79
   VelocityDb.TypeInfo.DataMember.a(Byte[] A_0, Int32& A_1, Object A_2, IOptimizedPersistable A_3, SessionBase A_4, Page A_5, Boolean A_6, Schema A_7, Boolean A_8, List`1 A_9, Int32 A_10, Int32 A_11, Boolean A_12) +804
   VelocityDb.OptimizedPersistable.ReadMeUsingSchemaReflection(TypeVersion typeVersion, Byte[] memberBytes, Int32& offset, IOptimizedPersistable pObj, SessionBase session, Page page, Boolean useOidShort, Schema schema, Boolean openRefs, List`1 toLoadMembers, Int32 graphDepth, Int32 graphDepthToLoad, Boolean primitivesOnly) +481
   VelocityDb.TypeInfo.TypeVersion.LoadMembers(IOptimizedPersistable toLoad, Schema schema, List`1 toLoadMembers, Int32 graphDepth, Int32 graphDepthToLoad, SessionBase session, Boolean primitivesOnly) +372
   VelocityDb.TypeInfo.Schema.a(Byte[] A_0, Boolean A_1, SessionBase A_2, UInt64 A_3, Page A_4, Boolean A_5, List`1 A_6, Int32 A_7, Int32 A_8, TypeVersion A_9) +787
   VelocityDb.Page.Slot(UInt64 oid, Boolean openRefs, SessionBase session, Schema schema, Boolean iteration, List`1 toLoadMembers, Int32 graphDepth, Int32 graphDepthToLoad, TypeVersion shape) +801
   VelocityDb.Session.SessionBase.Open(UInt64 oid, Boolean update, List`1 toLoadMembers, Boolean inFlush, Int32 graphDepth, Int32 graphDepthToLoad, Boolean signalNotExistError) +648
   VelocityDb.Collection.BTree.BTreeSet`1.GetKey(Int32 index) +161
   VelocityDb.Collection.BTree.BTreeBase`2.binarySearch(Key aKey, Byte[] comparisonArrayIn, Boolean& isEqual) +668
   VelocityDb.Collection.BTree.BTreeBase`2.RemoveFromLeafRoot(Key key, Byte[] comparisonArray) +27
   VelocityDb.Collection.BTree.BTreeBase`2.Remove(Key key, Byte[] comparisonArray) +66
   VelocityDb.Session.SessionBase.deleteFromIndexes(IOptimizedPersistable pObjBeforeUpdates, TypeVersion typeVersion, TypeVersion objTypeVersion) +1134
   VelocityDb.Session.SessionBase.a(IOptimizedPersistable A_0) +155
   VelocityDb.Session.SessionBase.UpdateObject(IOptimizedPersistable obj, Boolean inFlush, Boolean deleteObjFromIndexes) +314
   VelocityDb.OptimizedPersistable.UpdateTypeVersion() +227

What do I do wrong?

Lazy using BTree collection

When I use BTreeSet<T> or BTreeMap<S,T> (where S is value type, T is OptimizedPersistable), how can I get just OID instead of full object? I.e. when using 

set.Where(x=>x.Id==1).First() 

or

map[id]

Sometimes I don't need to open full non-cached object from network and disk and I just want to get its oid (an element of internal keysArray or valuesArray). Is there any way to achieve it  ? Maybe is there some extension for this collections there?

Count of the objects per page

Would be performance affected if we store millions of frequently updated objects  with objectsPerPage = 1 (to avoid page locking for server session)? The storage is not considered

ServerClientSession - caching and multithreading.

1) Where does it cache data? In memory on server side or client side? If I am using such code

var session = getCachedSession();
session.BeginRead();
var data = GetData();
session.Commit();
return data;

then next GetData() always opens objects from server disk (even with CacheEnum.Yes).

If the code just like that:

var session = getCachedSession(); //long read transaction
return GetData();

then GetData() immediately gets data from client memory. I don't want to store data in client's memory. How can I cache data only in the memory of the server till first update of related pages? What about caching of system databases (schema, locations etc)?

2) What is proper usage of ServerClientSession in multiple threads (in one process)? I see, the class itself is not thread-safe, and creation of an instance is expensive. Is there any way to make its singleton instance thread-safe (without lock(session) )? In the moment I am manually maintaining a pool of several initialized ServerClientSession using ConcurrentStack; each thread pops (creates if needed) and pushes back own instance with separate transaction block (BeginRead/Update - Commit block). Maybe is there better approach that we could use?

Autoincrementing fields

Can you provide autoincrementing fields of numeric types in persistent objects by implementing a field attribute like [AutoIncrement] ? One will be able to add that attribute to field with

 [Index][UniqueConstraint]

but the field value is automatically incremented when object is persisted.

It must be retroactive if there are objects with such fields persisted already. For example if we had imported the objects with specified fields values with compiled class without that attribute, then next time after we put that attribute and compile it, Session must get the last value in indexed fields and increment it for new object.

ServerClientSession slow performance.

We have the issues with slow usage of ServerClientSession in local network. Version of VelocityDb is 3.13.1. Toggled TcpClient.NoDelay does not help.

First of all, let me to show some benchmarks made by Database Benchmark 2.0.3 . I've just added benchmark for ClientServerSession leading to localhost (same PC with client) and second one leading to remote host (in same network as client).

Write speed

Read speed

Secondary read speed

As you can see, result of ServerClientSession connecting to remote host is very slow. Do you have any benchmark results for ServerClientSession?

There is the source code of an example, the usage of session and classes in it are similar to my models in web application. The program also runs very slow on the network (especially for read of 10 objects on wire). There are the profiler results. You can see that the huge bottleneck occurs in network code (like Socket.Receive). Elapsed time in hundreds milliseconds is not so acceptable.

What can you suggest? Or maybe is there some bottleneck in requests loop in VelocityDbServer or something like that?