Simple to advanced sample applications using VelocityDB and VelocityGraph

Expand/Contract each of the following samples by clicking on the + or - signs. All of these samples are also available in a sample solution included in the download and on GitHub. Open the sample solution by using the shortcut in the VelocityDB start menu or by going to your Documents\VelocityDB folder and opening VelocityDb.sln.

VelocityDB Sample Applications

Person.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using VelocityDb;

namespace VelocityDbSchema.Samples.Sample1
{
  public class Person : OptimizedPersistable
  {
    string firstName;
    string lastName;
    UInt16 age;

    public Person(string firstName, string lastName, UInt16 age)
    {
      this.firstName = firstName;
      this.lastName = lastName;
      this.age = age;
    }
  }
}

Sample1.cs

using System;
using VelocityDb.Session;
using VelocityDbSchema.Samples.Sample1;

namespace Sample1
{
  class Sample1
  {
    static readonly string systemDir = "Sample1"; // appended to SessionBase.BaseDatabasePath

    static int Main(string[] args)
    {
      using (SessionNoServer session = new SessionNoServer(systemDir))
      {
        Console.WriteLine("Running with databases in directory: " + session.SystemDirectory);
        session.BeginUpdate();
        Person person = new Person("Robin", "Hood", 30);
        session.Persist(person);
        person = new Person("Bill", "Gates", 56);
        session.Persist(person);
        person = new Person("Steve", "Jobs", 56);
        session.Persist(person);
        session.Commit();
      }
      return 0;
    }
  }
}

Looking at the Person objects in the DatabaseManager

Person.cs

using System;
using VelocityDb;

namespace VelocityDbSchema.Samples.Sample2
{
  public class Person : OptimizedPersistable
  {
    string m_firstName;
    string m_lastName;
    UInt16 m_age;
    Person m_bestFriend;

    public Person(string firstName, string lastName, UInt16 age, Person bestFriend = null)
    {
      m_firstName = firstName;
      m_lastName = lastName;
      m_age = age;
      m_bestFriend = bestFriend;
    }

    public Person BestFriend
    {
      get
      {
        return m_bestFriend;
      }
      set
      {
        Update();
        m_bestFriend = value;
      }
    }
  }
}

Sample2.cs

using VelocityDb.Session;
using VelocityDbSchema.Samples.Sample2;

namespace Sample2
{
  class Sample2
  {
    static readonly string systemDir = "Sample2"; // appended to SessionBase.BaseDatabasePath

    static void Main(string[] args)
    {
      using (SessionNoServer session = new SessionNoServer(systemDir))
      {
        session.BeginUpdate();
        Person robinHood = new Person("Robin", "Hood", 30);
        Person billGates = new Person("Bill", "Gates", 56, robinHood);
        Person steveJobs = new Person("Steve", "Jobs", 56, billGates);
        robinHood.BestFriend = billGates;
        session.Persist(steveJobs); // the other persons will be persisted implicetly by reachability from "Steve Jobs" person object
        session.Commit();
      }
    }
  }
}

Looking at the Sample 2 Person objects through the DatabaseManager

When using VelocityDbList instreade of List, the list is assigned an Oid instead of being directly embedded in the parent object. If a list is to be shared between multiple objects then VelocityDbList should be used.

Person.cs

using System;
using VelocityDb;
using VelocityDb.Collection;

namespace VelocityDbSchema.Samples.Sample4
{
  public class Person : OptimizedPersistable
  {
    string m_firstName;
    string m_lastName;
    UInt16 m_age;
    Person m_bestFriend;
    VelocityDbList<Person> m_friends;

    public Person(string firstName, string lastName, UInt16 age, Person bestFriend = null)
    {
      m_firstName = firstName;
      m_lastName = lastName;
      m_age = age;
      m_bestFriend = bestFriend;
      m_friends = new VelocityDbList<Person>();
    }

    public Person BestFriend
    {
      get
      {
        return m_bestFriend;
      }
      set
      {
        Update();
        m_bestFriend = value;
      }
    }

    public string FirstName
    {
      get
      {
        return m_firstName;
      }
      set
      {
        Update();
        m_firstName = value;
      }
    }

    public VelocityDbList<Person> Friends
    {
      get
      {
        return m_friends;
      }
    }
  }
}

Looking at the objects through the DatabaseManager

Main program of Sample4. It also shows how to unpersist (delete from database) objects and how to use fuzzy string matching

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using VelocityDb;
using VelocityDb.Session;
using VelocityDbSchema.Samples.Sample4;
using VelocityDb.Collection;
using System.IO;
using FuzzyString;

namespace Sample4
{
  class Sample4
  {
    static readonly string s_systemDir = "Sample4"; // appended to SessionBase.BaseDatabasePath

    static void Main(string[] args)
    {
      try
      {
        SessionBase.DefaultCompressPages = PageInfo.compressionKind.LZ4;
        using (SessionNoServer session = new SessionNoServer(s_systemDir))
        {
          Console.WriteLine("Running with databases in directory: " + session.SystemDirectory);
          session.BeginUpdate();
          // delete (unpersist) all Person objects created in prior run
          foreach (Person p in session.AllObjects<Person>())
            p.Unpersist(session);
          // delete (unpersist) all VelocityDbList<Person> objects created in prior run
          foreach (VelocityDbList<Person> l in session.AllObjects<VelocityDbList<Person>>())
            l.Unpersist(session);
          Person robinHood = new Person("Robin", "Hood", 30);
          Person billGates = new Person("Bill", "Gates", 56, robinHood);
          Person steveJobs = new Person("Steve", "Jobs", 56, billGates);
          robinHood.BestFriend = billGates;
          session.Persist(steveJobs);
          steveJobs.Friends.Add(billGates);
          steveJobs.Friends.Add(robinHood);
          billGates.Friends.Add(billGates);
          robinHood.Friends.Add(steveJobs);
          session.Commit();
        }
        using (SessionNoServer session = new SessionNoServer(s_systemDir))
        {
          List<FuzzyStringComparisonOptions> options = new List<FuzzyStringComparisonOptions>();

          // Choose which algorithms should weigh in for the comparison
          options.Add(FuzzyStringComparisonOptions.UseOverlapCoefficient);
          options.Add(FuzzyStringComparisonOptions.UseLongestCommonSubsequence);
          options.Add(FuzzyStringComparisonOptions.UseLongestCommonSubstring);
          options.Add(FuzzyStringComparisonOptions.UseHammingDistance);
          options.Add(FuzzyStringComparisonOptions.UseJaccardDistance);
          options.Add(FuzzyStringComparisonOptions.UseJaroDistance);
          options.Add(FuzzyStringComparisonOptions.UseJaroWinklerDistance);
          options.Add(FuzzyStringComparisonOptions.UseLevenshteinDistance);
          options.Add(FuzzyStringComparisonOptions.UseRatcliffObershelpSimilarity);
          options.Add(FuzzyStringComparisonOptions.UseSorensenDiceDistance);
          options.Add(FuzzyStringComparisonOptions.UseTanimotoCoefficient);


          // Choose the relative strength of the comparison - is it almost exactly equal? or is it just close?
          FuzzyStringComparisonTolerance tolerance = FuzzyStringComparisonTolerance.Normal;

          session.BeginRead();
          foreach (Person p in session.AllObjects<Person>())
          {
            // Get a boolean determination of approximate equality
            foreach (string firstNameFuzzy in new string[] { "Rob", "Billy", "Mats", "Stevo", "stevo" })
            {
              bool result = firstNameFuzzy.ApproximatelyEquals(p.FirstName, options, tolerance);
              if (result)
                Console.WriteLine(firstNameFuzzy + " approximatly equals " + p.FirstName);
            }
          }
          session.Commit();
        }
      }
      catch (Exception ex)
      {
        Console.WriteLine(ex.ToString());
      }
    }
  }
}
using System;
using System.Collections.Generic;
using System.Linq;
using VelocityDb.Session;
using VelocityDBExtensions;
using VelocityDbSchema.Samples.Sample4;

namespace JsonExportImport
{
  class JsonExportImport
  {
    static readonly string s_systemDirToImport = "Sample4"; // appended to SessionBase.BaseDatabasePath
    static readonly string s_systemDir = "JsonExportImport"; // appended to SessionBase.BaseDatabasePath

    static void Main(string[] args)
    {
      try
      {
        int personCt = 0;
        using (SessionBase session = new SessionNoServer(s_systemDirToImport))
        {
          session.BeginRead();
          IEnumerable<string> personStringEnum = session.ExportToJson<Person>();
          using (SessionBase sessionImport = new SessionNoServer(s_systemDir))
          {
            sessionImport.BeginUpdate();
            foreach (string json in personStringEnum)
            {
              Person person = sessionImport.ImportJson<Person>(json);
              sessionImport.Persist(person);
              personCt++;
            }
            session.Commit();
            sessionImport.Commit();
            Console.WriteLine("Imported " + personCt + " from Json strings");
          }
        }
      }
      catch (Exception ex)
      {
        Console.WriteLine(ex.ToString());
      }
    }
  }
}

The following code shows how high availabilty is achieved using VelocityDB. Test first connects to one server with a requested backup (like replica) to another server. Then we delete all the database files from the original server and quickly make a restore to another server and continue operating with no data loss.

   1:  // This application shows how to accomplish High Availability with VelocityDB. 
   2:  // It can be done with in memory data or persisted data replicated to a backup server that can take over as a master server on demand.
   3:   
   4:  using System;
   5:  using System.Collections.Generic;
   6:  using System.IO;
   7:  using System.Linq;
   8:  using System.Net;
   9:  using System.Text;
  10:  using System.Threading.Tasks;
  11:  using VelocityDb;
  12:  using VelocityDb.Session;
  13:  using VelocityDbSchema;
  14:   
  15:  namespace BackupRestore
  16:  {
  17:    class HighAvailability
  18:    {
  19:      static readonly string systemDir = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
  20:        "VelocityDB" + Path.DirectorySeparatorChar + "Databases" + Path.DirectorySeparatorChar + "HighAvailability");
  21:      static string systemHost = Dns.GetHostName();
  22:      static string backupHost = "FindPriceBuy"; // modify to second server name that you are using (make sure VelocityDB is installed on that server first)
  23:      static readonly string backupDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "VelocityDB", "Databases" + Path.DirectorySeparatorChar + "HighAvailabilityBackup");
  24:      static bool inMemoryOnly = false;
  25:      public static readonly uint backupLocationStartDbNum = (uint)Math.Pow(2, 26);
  26:      public void CreateDataWithBackupServer()
  27:      {
  28:        int loops = 30000;
  29:        int j;
  30:        using (ServerClientSession session = new ServerClientSession(systemDir, systemHost, 1000, true, inMemoryOnly))
  31:        {
  32:          Man aMan = null;
  33:          Woman aWoman = null;
  34:          const bool isBackupLocation = true;
  35:          session.BeginUpdate();
  36:          // we need to have backup locations special since server is not supposed to do encryption or compression
  37:          DatabaseLocation backupLocation = new DatabaseLocation(backupHost, backupDir, backupLocationStartDbNum, UInt32.MaxValue, session,
  38:            false, PageInfo.encryptionKind.noEncryption, isBackupLocation, session.DatabaseLocations.Default());
  39:          session.NewLocation(backupLocation);
  40:          session.Commit();
  41:          session.BeginUpdate();
  42:          for (j = 1; j <= loops; j++)
  43:          {
  44:            aMan = new Man(null, aMan, j, DateTime.Now);
  45:            session.Persist(aMan);
  46:            aWoman = new Woman(aMan, aWoman, j);
  47:            session.Persist(aWoman);
  48:            aMan.spouse = new VelocityDb.WeakIOptimizedPersistableReference<VelocityDbSchema.Person>(aWoman);
  49:            if (j % 1000000 == 0)
  50:              Console.WriteLine("Loop # " + j);
  51:          }
  52:          UInt64 id = aWoman.Id;
  53:          Console.WriteLine("Commit, done Loop # " + j);
  54:          session.Commit();
  55:        }
  56:      }
  57:   
  58:      public void CreateMoreDataWithBackupServer()
  59:      {
  60:        int loops = 1000;
  61:        int j;
  62:        using (ServerClientSession session = new ServerClientSession(systemDir, systemHost, 1000, true, inMemoryOnly))
  63:        {
  64:          Man aMan = null;
  65:          Woman aWoman = null;
  66:          session.BeginUpdate();
  67:          for (j = 1; j <= loops; j++)
  68:          {
  69:            aMan = new Man(null, aMan, j, DateTime.Now);
  70:            session.Persist(aMan);
  71:            aWoman = new Woman(aMan, aWoman, j);
  72:            session.Persist(aWoman);
  73:            aMan.spouse = new VelocityDb.WeakIOptimizedPersistableReference<VelocityDbSchema.Person>(aWoman);
  74:            if (j % 1000000 == 0)
  75:              Console.WriteLine("Loop # " + j);
  76:          }
  77:          UInt64 id = aWoman.Id;
  78:          Console.WriteLine("Commit, done Loop # " + j);
  79:          session.FlushUpdates();
  80:          ReadSomeData(); // read some with uncommited cached server data
  81:          session.Commit();
  82:        }
  83:      }
  84:   
  85:      public void ReadSomeData()
  86:      {
  87:        int ct = 0;
  88:        using (ServerClientSession session = new ServerClientSession(systemDir, systemHost, 1000, true, inMemoryOnly))
  89:        {
  90:          session.BeginRead();
  91:          foreach (Man man in session.AllObjects<Man>())
  92:          {
  93:            ct++;
  94:          }
  95:          Console.WriteLine("Commit, number of Men found: " + ct);
  96:          session.Commit();
  97:        }
  98:      }
  99:   
 100:      public void RestoreToBackupServer()
 101:      {
 102:        using (ServerClientSession session = new ServerClientSession(systemDir, systemHost))
 103:        {
 104:          session.ClearServerCache(); // normally don't use this function but use it here to simulate a server going down and restarting
 105:        }
 106:   
 107:        using (ServerClientSession session = new ServerClientSession(systemDir, backupHost, 1000, true, inMemoryOnly))
 108:        {
 109:          session.BeginUpdate();
 110:          DatabaseLocation backupLocation = new DatabaseLocation(backupHost, backupDir, backupLocationStartDbNum, UInt32.MaxValue, session,
 111:            false, PageInfo.encryptionKind.noEncryption, true, session.DatabaseLocations.Default());
 112:          session.RestoreFrom(backupLocation, DateTime.MaxValue);
 113:          session.Commit(false, true);
 114:        }
 115:      }
 116:   
 117:      public void DeleteBackupLocation()
 118:      {
 119:        using (ServerClientSession session = new ServerClientSession(systemDir, systemHost, 1000, true, inMemoryOnly))
 120:        {
 121:          session.BeginUpdate();
 122:          DatabaseLocation backupLocation = session.DatabaseLocations.LocationForDb(backupLocationStartDbNum);
 123:          List<Database> dbList = session.OpenLocationDatabases(backupLocation, true);
 124:          foreach (Database db in dbList)
 125:            session.DeleteDatabase(db);
 126:          session.DeleteLocation(backupLocation);
 127:          session.Commit();
 128:        }
 129:      }
 130:      public void DeleteDefaultLocation()
 131:      {
 132:        using (ServerClientSession session = new ServerClientSession(systemDir, systemHost, 1000, true, inMemoryOnly))
 133:        {
 134:          session.BeginUpdate();
 135:          DatabaseLocation defaultLocation = session.DatabaseLocations.Default();
 136:          List<Database> dbList = session.OpenLocationDatabases(defaultLocation, true);
 137:          foreach (Database db in dbList)
 138:            if (db.DatabaseNumber > Database.InitialReservedDatabaseNumbers)
 139:              session.DeleteDatabase(db);
 140:          session.DeleteLocation(defaultLocation);
 141:          session.Commit();
 142:        }
 143:      }
 144:   
 145:      static void Main(string[] args)
 146:      {
 147:        if (args.Length > 0) // pass any argument to to command line to force use of persisted data.
 148:          inMemoryOnly = false;
 149:        HighAvailability ha = new HighAvailability();
 150:        try
 151:        {
 152:          ha.CreateDataWithBackupServer();
 153:          ha.ReadSomeData();
 154:          ha.CreateMoreDataWithBackupServer();
 155:          ha.ReadSomeData();
 156:          if (Directory.Exists(systemDir))
 157:            Directory.Delete(systemDir, true); // remove our current systemDir and all its databases.
 158:          ha.RestoreToBackupServer();
 159:          string t = systemHost; // swap backupHost and systemHost
 160:          systemHost = backupHost;
 161:          backupHost = t;
 162:          ha.ReadSomeData();
 163:          ha.CreateMoreDataWithBackupServer();
 164:          ha.ReadSomeData();
 165:          ha.DeleteBackupLocation();
 166:          ha.DeleteDefaultLocation(); // so that we can rerun this sample
 167:        }
 168:        catch (Exception ex)
 169:        {
 170:          Console.WriteLine("Exception: {0}", ex);
 171:   
 172:        }
 173:      }
 174:    }
 175:  }

Here are some classes with defined indexes

   1:    [UniqueConstraint]
   2:    [Index("registrationState,registrationPlate")]
   3:    public class Car : Vehicle
   4:    {
   5:      string registrationState;
   6:      string registrationPlate;
   7:      [Index]
   8:      InsuranceCompany insuranceCompany;
   9:      string insurancePolicy;
  10:   
  11:      public Car(string color, int maxPassengers, int fuelCapacity, double litresPer100Kilometers, DateTime modelYear,
  12:        string brandName, string modelName, int maxSpeed, int odometer, string registrationState, string registrationPlate,
  13:        InsuranceCompany insuranceCompany, string insurancePolicy)
  14:        : base(color, maxPassengers, fuelCapacity, litresPer100Kilometers, modelYear, brandName, modelName, maxSpeed, odometer)
  15:      {
  16:        this.registrationState = registrationState;
  17:        this.registrationPlate = registrationPlate;
  18:        this.insuranceCompany = insuranceCompany;
  19:        this.insurancePolicy = insurancePolicy;
  20:      }
  21:    }
  22:   
  23:    [Index("stateOrCountry,licenseNumber")]
  24:    public class DriversLicense : OptimizedPersistable
  25:    {
  26:      string stateOrCountry;
  27:      string licenseNumber;
  28:      DateTime dateIssued;
  29:   
  30:      [Index]
  31:      DateTime validUntil;
  32:   
  33:      public DriversLicense(string stateOrCountry, string licenseNumber, DateTime validUntil)
  34:      {
  35:        this.stateOrCountry = stateOrCountry;
  36:        this.licenseNumber = licenseNumber;
  37:        this.dateIssued = DateTime.Now;
  38:        this.validUntil = validUntil;
  39:      }
  40:   
  41:      [FieldAccessor("validUntil")]
  42:      public DateTime ValidUntil
  43:      {
  44:        get
  45:        {
  46:          return validUntil;
  47:        }
  48:      }
  49:    }
  50:   
  51:    public class InsuranceCompany : OptimizedPersistable
  52:    {
  53:      [Index]
  54:      [UniqueConstraint]
  55:      [OnePerDatabase]
  56:      string name;
  57:      string phoneNumber;
  58:   
  59:      public InsuranceCompany(string name, string phoneNumber)
  60:      {
  61:        this.name = name;
  62:        this.phoneNumber = phoneNumber;
  63:      }
  64:   
  65:      [FieldAccessor("name")]
  66:      public string Name
  67:      {
  68:        get
  69:        {
  70:          return name;
  71:        }
  72:      }
  73:    }
  74:   
  75:    [Index]
  76:    public class Person : OptimizedPersistable
  77:    {
  78:      string name;
  79:      DriversLicense license;
  80:   
  81:      public Person(string name, DriversLicense license)
  82:      {
  83:        this.name = name;
  84:        this.license = license;
  85:      }
  86:    }
  87:   
  88:    public class Truck : Vehicle
  89:    {
  90:      string registrationState;
  91:      string registrationPlate;
  92:      InsuranceCompany insuranceCompany;
  93:      string insurancePolicy;
  94:      int cargoCapacity; // in Kg
  95:   
  96:      public Truck(string color, int maxPassengers, int fuelCapacity, double litresPer100Kilometers, DateTime modelYear,
  97:        string brandName, string modelName, int maxSpeed, int odometer, string registrationState, string registrationPlate,
  98:        InsuranceCompany insuranceCompany, string insurancePolicy, int cargoCapacity)
  99:        : base(color, maxPassengers, fuelCapacity, litresPer100Kilometers, modelYear, brandName, modelName, maxSpeed, odometer)
 100:      {
 101:        this.registrationState = registrationState;
 102:        this.registrationPlate = registrationPlate;
 103:        this.insuranceCompany = insuranceCompany;
 104:        this.insurancePolicy = insurancePolicy;
 105:        this.cargoCapacity = cargoCapacity;
 106:      }
 107:    }
 108:    [Index("modelYear,brandName,modelName,color")]
 109:    public abstract class Vehicle : OptimizedPersistable
 110:    {
 111:      [Index]
 112:      string color;
 113:      int maxPassengers;
 114:      int fuelCapacity; // fuel capacity in liters   
 115:      [Index]
 116:      double litresPer100Kilometers; // fuel cunsumption 
 117:      DateTime modelYear;
 118:      [Index]
 119:      [IndexStringByHashCode]
 120:      string brandName;
 121:      string modelName;
 122:      int maxSpeed; // km/h
 123:      int odometer; // km
 124:   
 125:      protected Vehicle(string color, int maxPassengers, int fuelCapacity, double litresPer100Kilometers, DateTime modelYear, string brandName, string modelName, int maxSpeed, int odometer)
 126:      {
 127:        this.color = color;
 128:        this.maxPassengers = maxPassengers;
 129:        this.fuelCapacity = fuelCapacity;
 130:        this.litresPer100Kilometers = litresPer100Kilometers;
 131:        this.modelYear = modelYear;
 132:        this.brandName = brandName;
 133:        this.modelName = modelName;
 134:        this.maxSpeed = maxSpeed;
 135:        this.odometer = odometer;
 136:      }
 137:   
 138:      [FieldAccessor("color")]
 139:      public string Color
 140:      {
 141:        get
 142:        {
 143:          return color;
 144:        }
 145:        set
 146:        {
 147:          Update();
 148:          color = value;
 149:        }
 150:      }
 151:   
 152:      [FieldAccessor("litresPer100Kilometers")]
 153:      public double LitresPer100Kilometers
 154:      {
 155:        get
 156:        {
 157:          return litresPer100Kilometers;
 158:        }
 159:      }
 160:    }

Using these indexes

   1:    class Indexes
   2:    {
   3:      static readonly string systemDir = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
   4:        "VelocityDB" + Path.DirectorySeparatorChar + "Databases" + Path.DirectorySeparatorChar + "Indexes");
   5:   
   6:      static void Main(string[] args)
   7:      {
   8:        try
   9:        {
  10:          string brandName = "Toyota";
  11:          string color = "Blue";
  12:          int maxPassengers = 5;
  13:          int fuelCapacity = 40;
  14:          double litresPer100Kilometers = 5;
  15:          DateTime modelYear = new DateTime(2003, 1, 1);
  16:          string modelName = "Highlander";
  17:          int maxSpeed = 200;
  18:          int odometer = 100000;
  19:          string registrationState = "Texas";
  20:          string registrationPlate = "TX343434";
  21:          string insurancePolicy = "CAA7878787";
  22:          DriversLicense license = new DriversLicense("California", "B7788888", DateTime.Now + new TimeSpan(1825, 0, 0, 0));
  23:          Person person = new Person("Mats Persson", license);
  24:          InsuranceCompany insuranceCompany = new InsuranceCompany("Allstate", "858727878");
  25:          Car car = new Car(color, maxPassengers, fuelCapacity, litresPer100Kilometers, modelYear, brandName, modelName, maxSpeed,
  26:            odometer, registrationState, registrationPlate, insuranceCompany, insurancePolicy);
  27:          using (SessionNoServer session = new SessionNoServer(systemDir))
  28:          { // cleanup data from a possible prior run
  29:            session.BeginUpdate();
  30:            foreach (Database db in session.OpenAllDatabases(true))
  31:              if (db.DatabaseNumber >= 10 || db.DatabaseNumber == SessionBase.IndexDescriptorDatabaseNumber)
  32:                session.DeleteDatabase(db);
  33:            session.Commit();
  34:          }
  35:          using (SessionNoServer session = new SessionNoServer(systemDir))
  36:          {
  37:            session.BeginUpdate();
  38:            session.Persist(car);
  39:            registrationState = "Maine";
  40:            car = new Car(color, maxPassengers, fuelCapacity, litresPer100Kilometers, modelYear, brandName, modelName, maxSpeed,
  41:            odometer, registrationState, registrationPlate, insuranceCompany, insurancePolicy);
  42:            session.Persist(car);
  43:            color = "Red";
  44:            maxPassengers = 5;
  45:            fuelCapacity = 50;
  46:            litresPer100Kilometers = 8;
  47:            modelYear = new DateTime(2006, 1, 1);
  48:            brandName = "Toyota";
  49:            modelName = "Tacoma";
  50:            maxSpeed = 210;
  51:            odometer = 50000;
  52:            registrationState = "Texas";
  53:            registrationPlate = "TX343433";
  54:            insurancePolicy = "CAA7878777";
  55:            car = new Car(color, maxPassengers, fuelCapacity, litresPer100Kilometers, modelYear, brandName, modelName, maxSpeed,
  56:              odometer, registrationState, registrationPlate, insuranceCompany, insurancePolicy);
  57:            session.Persist(car);
  58:            color = "Black";
  59:            maxPassengers = 5;
  60:            fuelCapacity = 60;
  61:            litresPer100Kilometers = 3;
  62:            modelYear = new DateTime(2001, 1, 1);
  63:            brandName = "Lincoln";
  64:            modelName = "Town Car";
  65:            maxSpeed = 220;
  66:            odometer = 250000;
  67:            registrationState = "Texas";
  68:            registrationPlate = "TX543433";
  69:            insurancePolicy = "CAA7878775";
  70:            car = new Car(color, maxPassengers, fuelCapacity, litresPer100Kilometers, modelYear, brandName, modelName, maxSpeed,
  71:              odometer, registrationState, registrationPlate, insuranceCompany, insurancePolicy);
  72:            session.Persist(car);
  73:            session.Commit();
  74:          }
  75:          using (SessionNoServer session = new SessionNoServer(systemDir))
  76:          {
  77:            session.BeginRead();
  78:            Console.WriteLine("Blue Cars");
  79:            BTreeSet<Car> bTree = session.Index<Car>("color");
  80:            foreach (Car c in (from aCar in bTree where aCar.Color == "Blue" select aCar))
  81:              Console.WriteLine(c.ToStringDetails(session));
  82:            Console.WriteLine("Cars in fuel efficierncy order");
  83:            foreach (Car c in session.Index<Car>("litresPer100Kilometers"))
  84:              Console.WriteLine(c.ToStringDetails(session));
  85:            Console.WriteLine("Vehicles ordered modelYear, brandName, modelName, color");
  86:            foreach (Vehicle v in session.Index<Vehicle>())
  87:              Console.WriteLine(v.ToStringDetails(session));
  88:            session.Commit();
  89:          }
  90:          using (SessionNoServer session = new SessionNoServer(systemDir))
  91:          {
  92:            session.BeginUpdate();
  93:            // these LINQ statements will trigger a binary search lookup (not a linear serach) of the matching Car objects in the BTreeSet
  94:            Car c = (from aCar in session.Index<Car>("color") where aCar.Color == "Blue" select aCar).First();
  95:            c.Color = "Green";
  96:            session.Commit();
  97:          }
  98:          using (SessionNoServer session = new SessionNoServer(systemDir))
  99:          {
 100:            session.BeginUpdate();
 101:            // these LINQ statements will trigger a binary search lookup (not a linear serach) of the matching Car objects in the BTreeSet
 102:            Car c = (from aCar in session.Index<Car>("color") where aCar.Color == "Green" select aCar).First();
 103:            UInt64 id = c.Id;
 104:            session.DeleteObject(id);
 105:            session.Abort();
 106:            session.BeginUpdate();
 107:            session.DeleteObject(id);
 108:            session.Commit();
 109:          }
 110:          using (SessionNoServer session = new SessionNoServer(systemDir))
 111:          {
 112:            Stopwatch sw = new Stopwatch();
 113:            sw.Start();
 114:            session.BeginRead();
 115:            // these LINQ statements will trigger a binary search lookup (not a linear serach) of the matching Car objects in the BTreeSet
 116:            Console.WriteLine("Blue Cars");
 117:            foreach (Car c in (from aCar in session.Index<Car>("color") where aCar.Color == "Blue" select aCar))
 118:              Console.WriteLine(c.ToStringDetails(session));
 119:            session.Commit();
 120:            sw.Stop();
 121:            Console.WriteLine(sw.Elapsed);
 122:          }
 123:          using (SessionNoServer session = new SessionNoServer(systemDir))
 124:          {
 125:            Stopwatch sw = new Stopwatch();
 126:            sw.Start();
 127:            session.BeginUpdate();
 128:            for (int i = 0; i < 10000; i++)
 129:            { // add some junk to make search harder
 130:              car = new Car(color, maxPassengers, fuelCapacity, litresPer100Kilometers, modelYear, brandName, modelName, i,
 131:              odometer, registrationState, registrationPlate + i, insuranceCompany, insurancePolicy);
 132:              session.Persist(car);
 133:            }
 134:            session.Commit();
 135:            sw.Stop();
 136:            Console.WriteLine(sw.Elapsed);
 137:          }
 138:          using (SessionNoServer session = new SessionNoServer(systemDir))
 139:          {
 140:            Stopwatch sw = new Stopwatch();
 141:            sw.Start();
 142:            session.BeginRead();
 143:            // these LINQ statements will trigger a binary search lookup (not a linear serach) of the matching Car objects in the BTreeSet
 144:            Console.WriteLine("Blue Cars");
 145:            foreach (Car c in (from aCar in session.Index<Car>("color") where aCar.Color == "Blue" select aCar))
 146:              Console.WriteLine(c.ToStringDetails(session));
 147:            session.Commit();
 148:            sw.Stop();
 149:            Console.WriteLine(sw.Elapsed);
 150:          }
 151:          using (SessionNoServer session = new SessionNoServer(systemDir))
 152:          {
 153:            Stopwatch sw = new Stopwatch();
 154:            sw.Start();
 155:            session.BeginUpdate();
 156:            Car c = (from aCar in session.Index<Car>("color") where aCar.Color == "Blue" select aCar).First();
 157:            c.Unpersist(session);
 158:            session.Commit();
 159:            sw.Stop();
 160:            Console.WriteLine(sw.Elapsed);
 161:          }
 162:          using (SessionNoServer session = new SessionNoServer(systemDir))
 163:          {
 164:            Stopwatch sw = new Stopwatch();
 165:            sw.Start();
 166:            session.BeginRead();
 167:            foreach (Car c in session.Index<Car>())
 168:              Console.WriteLine(c.ToStringDetails(session));
 169:            Console.WriteLine("Blue Cars");
 170:            foreach (Car c in (from aCar in session.Index<Car>() where aCar.Color == "Blue" select aCar))
 171:              Console.WriteLine(c.ToStringDetails(session));
 172:            session.Commit();
 173:            sw.Stop();
 174:            Console.WriteLine(sw.Elapsed);
 175:          }
 176:          using (SessionNoServer session = new SessionNoServer(systemDir))
 177:          {
 178:            Stopwatch sw = new Stopwatch();
 179:            sw.Start();
 180:            session.BeginUpdate();
 181:            InsuranceCompany prior = insuranceCompany;
 182:            try
 183:            {
 184:              for (int i = 0; i < 100000; i++)
 185:              {
 186:                insuranceCompany = new InsuranceCompany("AAA", "858787878");
 187:                session.Persist(insuranceCompany);
 188:              }
 189:              Debug.Assert(false); // should not get here
 190:            }
 191:            catch (UniqueConstraintException)
 192:            {
 193:            }
 194:            session.Commit();
 195:            sw.Stop();
 196:            Console.WriteLine(sw.Elapsed);
 197:          }
 198:          using (SessionNoServer session = new SessionNoServer(systemDir))
 199:          {
 200:            Stopwatch sw = new Stopwatch();
 201:            sw.Start();
 202:            session.BeginRead();
 203:            Database db = session.OpenDatabase(session.DatabaseNumberOf(typeof(InsuranceCompany)));
 204:            var q = from company in session.Index<InsuranceCompany>("name", db) where company.Name == "AAA" select company;
 205:            foreach (InsuranceCompany company in q)
 206:              Console.WriteLine(company.ToStringDetails(session)); // only one will match
 207:            session.Commit();
 208:            sw.Stop();
 209:            Console.WriteLine(sw.Elapsed);
 210:          }
 211:        }
 212:        catch (Exception ex)
 213:        {
 214:          Console.WriteLine(ex.ToString());
 215:        }
 216:      }
 217:    }
   1:  // This sample console application demonstrates the usage of the event subscription ServerClientSession api. Get notified when other sessions changes objects your session is intrested in.
   2:  using System;
   3:  using System.Collections.Generic;
   4:  using System.IO;
   5:  using System.Linq;
   6:  using System.Text;
   7:  using System.Threading;
   8:  using System.Threading.Tasks;
   9:  using VelocityDb;
  10:  using VelocityDb.Session;
  11:  using VelocityDbSchema;
  12:   
  13:  namespace EventSubscriber
  14:  {
  15:    class EventSubscriber
  16:    {
  17:      static readonly string systemDir = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
  18:        "VelocityDB" + Path.DirectorySeparatorChar + "Databases" + Path.DirectorySeparatorChar + "EventSubscriber"); 
  19:   
  20:      static void Main(string[] args)
  21:      {
  22:        using (ServerClientSession session = new ServerClientSession(systemDir))
  23:        {
  24:          session.BeginUpdate();
  25:          session.SubscribeToChanges(typeof(Person));
  26:          session.SubscribeToChanges(typeof(Woman), "OlderThan50");
  27:          Person robinHood = new Person("Robin", "Hood", 30, 1234, null, null);
  28:          session.Persist(robinHood);
  29:          Person billGates = new Person("Bill", "Gates", 56, 234, robinHood, null);
  30:          session.Persist(billGates);
  31:          Person steveJobs = new Person("Steve", "Jobs", 56, 456, billGates, null);
  32:          session.Persist(steveJobs);
  33:          session.Commit();
  34:          Thread t = new Thread(UpdaterThread);
  35:          t.Start();
  36:          Thread.Sleep(600);
  37:          
  38:          for (int i = 0; i < 50; i++)
  39:          {
  40:            List<Oid> changes = session.BeginReadWithEvents();
  41:            if (changes.Count == 0)
  42:            {
  43:              Console.WriteLine("No changes events at: " + DateTime.Now.ToString("HH:mm:ss:ms"));
  44:              Thread.Sleep(250);
  45:            }
  46:            foreach (Oid id in changes)
  47:            {
  48:              object obj = session.Open(id);
  49:              Console.WriteLine("Received change event for: " + obj + " at: " + DateTime.Now.ToString("HH:mm:ss:ms"));;
  50:              //session.UnsubscribeToChanges(typeof(Person));
  51:            }
  52:            Console.WriteLine();
  53:            session.Commit();
  54:          }       
  55:          t.Join();
  56:        }
  57:      }
  58:   
  59:      static void UpdaterThread()
  60:      {
  61:        using (ServerClientSession session = new ServerClientSession(systemDir))
  62:        {
  63:          session.BeginUpdate();
  64:          Person Mats = new Person("Mats", "Persson", 22, 1234, null, null);
  65:          session.Persist(Mats);
  66:          Woman Kinga = new Woman("Kinga", "Persson", 56, 234, null, Mats);
  67:          foreach (Person p in session.AllObjects<Person>())
  68:          {
  69:            p.Age = (ushort) (p.Age + 1); 
  70:          }
  71:          session.Persist(Kinga);
  72:          session.Commit();
  73:  // 5 events
  74:          Thread.Sleep(5000);
  75:   
  76:          session.BeginUpdate();
  77:          Woman Lidia = new Woman("Lidia", "Persson", 22, 1234, null, null);
  78:          session.Persist(Lidia);
  79:          session.Commit();
  80:  // 0 events 
  81:          Thread.Sleep(500);
  82:   
  83:          session.BeginUpdate();
  84:          Woman Margareta = new Woman("Margareta", "Persson", 98, 1234, null, null);
  85:          session.Persist(Margareta);
  86:          session.Commit();
  87:  // 1 event
  88:          Thread.Sleep(500);
  89:   
  90:          session.BeginUpdate();
  91:          Woman Oliwia = new Woman("Oliwia", "Persson", 50, 1234, null, null);
  92:          session.Persist(Oliwia);
  93:          session.Commit();
  94:  // 0 events
  95:          Thread.Sleep(500);
  96:   
  97:          session.BeginUpdate();
  98:          foreach (Woman p in session.AllObjects<Woman>())
  99:          {
 100:            p.Age = (ushort) (p.Age + 1); 
 101:          }
 102:          session.Commit();
 103:  // 3 events
 104:          session.BeginUpdate();
 105:          foreach (Woman p in session.AllObjects<Woman>())
 106:          {
 107:            p.Age = (ushort)(p.Age + 1);
 108:          }
 109:          session.Commit();
 110:  // 3 events
 111:        }
 112:      }
 113:    }
 114:  }
  public class Person : OptimizedPersistable
  {
    static Random randGen = new Random(5);

    string firstName;
    string lastName;
    WeakReference<VelocityDbList<Person>> friendsRef;

    public Person(Person person = null) // creates a random Person object
    {
      int r = randGen.Next(99999);
      firstName = r.ToString();
      r = randGen.Next(99999999);
      lastName = r.ToString();
      VelocityDbList<Person> personList = new VelocityDbList<Person>();
      if (person != null && person.IsPersistent)
      {
        personList.Persist(person.Session, person);
        personList.Add(person);
        friendsRef = new WeakReference<VelocityDbList<Person>>(personList);
      }
    }

    public string FirstName
    {
      get
      {
        return firstName;
      }
      set
      {
        Update();
        firstName = value;
      }
    }

    public VelocityDbList<Person> Friends
    {
      get
      {
        return friendsRef.GetTarget(false, null);
      }
    }
  }

Usage

  class Program
  {
    static readonly string systemDir = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "VelocityDB", "Databases", "WeakReferences");

    const long numberOfPersons = 10000000000; // a billion Person objects - let's say it is more than we can fit in memory
    static void Main(string[] args)
    {
      try
      {
        using (SessionNoServer session = new SessionNoServer(systemDir))
        {
          session.BeginUpdate();
          Person person = new Person();
          for (long i = 0; i < numberOfPersons; i++)
          {
            // Each WeakReference require a persisted object (non null Oid) so that object reference can be substituted with an Oid.
            session.Persist(person);
            // create new Person and make prior Person his/her friend (see constructor of Person)
            person = new Person(person);
          }
          session.Commit();
        }
      }
      catch (Exception ex)
      {
        Console.WriteLine(ex.ToString());
      }
    }

The class AllSupported contains sample data fields of all (or most) kinds of types that have beed tested with VelocityDb. Let us know if we missed any kind of field type.

AllSupported.cs

  public class AllSupported : OptimizedPersistable
  {
    enum byteEnum : byte { a, b, c };
    enum int16Enum : short { a, b, c, d, e, f };
    enum int32Enum : int { a, b, c, d, e, f, g, h };
    enum int64Enum : long { a, b, c, dd, ee, ff };
    int[][] jaggedArray = new int[3][];
    Person person; 
    Pet aPet; // just a sample using a class that is not a subclass of OptimizedPersistable
    byteEnum enumByte;
    int16Enum enumInt16;
    int32Enum enumInt32;
    int64Enum enumInt64;
    PersistenceByInterfaceSnake aSnake;
    byte aByte;
    SByte sByte;
    string aString;
    char aChar;
    public float single;
    public double aDouble;
    public UInt16 uint16;
    public UInt32 uint32;
    public UInt64 uint64;
    public Int16 int16;
    public Int32 int32;
    public Int64 int64;
    public DateTime dateTime;
    public TimeSpan timeSpan;
    public Decimal aDecimal;
    byte? nullableByte;
    SByte? nullablesByte;
    char? nullableChar;
    public float? nullablesingle;
    public double? nullableaDouble;
    public UInt16? nullableuint16;
    public UInt32? nullableuint32;
    public UInt64? nullableuint64;
    public Int16? nullableint16;
    public Int32? nullableint32;
    public Int64? nullableint64;
    public DateTime? nullabledateTime;
    public TimeSpan? nullabletimeSpan;
    public Decimal? nullableDecimal;
    WeakReference<OptimizedPersistable> weakReference;
    byte?[] nullablebyteArray;
    char?[] nullablecharArray;
    UInt16?[] nullableuint16Array;
    UInt32?[] nullableuint32Array;
    UInt64?[] nullableuint64Array;
    Int16?[] nullableint16Array;
    Int32?[] nullableint32Array;
    Int64?[] nullableint64Array;
    float?[] nullablefloatArray;
    double?[] nullabledoubleArray;
    DateTime?[] nullableDateTimeArray;
    Decimal?[] nullableDecimalArray;
    Oid?[] nullableOidArray;
    byte[] byteArray;
    char[] charArray;
    UInt16[] uint16Array;
    UInt32[] uint32Array;
    UInt64[] uint64Array;
    Int16[] int16Array;
    Int32[] int32Array;
    Int64[] int64Array;
    float[] floatArray;
    double[] doubleArray;
    DateTime[] dateTimeArray;
    Oid[] oidArray;
    List<byte> listByte; // all List<> use wrapper OptimizedPersistable looked up from a parent collection
    List<Person> personList;
    List<WeakReference<OptimizedPersistable>> weakReferenceList;
    List<Int16> int16List;
    List<UInt16> uint16List;
    List<Int32> int32List;
    List<UInt32> uint32List;
    List<Int64> int64List;
    List<UInt64> uint64List;
    List<String> stringList;
    List<Oid> oidList;
    List<Oid?> nullableoidList;
    [UseOidShort]
    List<Pet> petListOidShort;
    List<Pet> petListLongOid;
    VelocityDbList<byte> odblistByte; // VelocityDbList is like List but is a subclass of OptimizedPersistable which makes it perform better by avoiding collection lookup
    VelocityDbList<Person> personOdbList;
    VelocityDbList<WeakReference<OptimizedPersistable>> weakReferenceOdbList;
    VelocityDbList<Int16> int16OdbList;
    VelocityDbList<UInt16> uint16OdbList;
    VelocityDbList<Int32> int32OdbList;
    VelocityDbList<UInt32> uint32OdbList;
    VelocityDbList<Int64> int64OdbList;
    VelocityDbList<UInt64> uint64OdbList;
    VelocityDbList<String> stringOdbList;
    VelocityDbList<Pet> petOdbList;
    ArrayList petList2;
    public Slot aSlot;
    public Slot[] m_slots;
    BTreeSet<Person> bTreePerson;
    SortedSetAny<Person> sortedSetPerson;
    SortedMap<byte, Person> sortedMapByteToPerson;
    VelocityDbHashSet<Person> personHashSet;
    public struct Slot
    {
      public int hashCode;
      public Person value;
      public int next;
    }
    public AllSupported(Int32 arraySize)
    {
      aSnake = new PersistenceByInterfaceSnake("Curly", 1, true, 58);
      jaggedArray[0] = new int[] { 1, 3, 5, 7, 9 };
      jaggedArray[1] = new int[] { 0, 2, 4, 6 };
      jaggedArray[2] = new int[] { 11, 22 };
      nullabledateTime = null;
      nullableByte = null;
      enumByte = byteEnum.b;
      enumInt16 = int16Enum.c;
      enumInt32 = int32Enum.f;
      enumInt64 = int64Enum.ff;
      byteArray = new byte[arraySize];
      charArray = new char[arraySize];
      uint16Array = new UInt16[arraySize];
      uint32Array = new UInt32[arraySize];
      uint64Array = new UInt64[arraySize];
      int16Array = new Int16[arraySize];
      int32Array = new Int32[arraySize];
      int64Array = new Int64[arraySize];
      floatArray = new float[arraySize];
      doubleArray = new double[arraySize];
      dateTimeArray = new DateTime[arraySize];
      oidArray = new Oid[arraySize];
      nullablebyteArray = new byte?[arraySize];
      nullablecharArray = new char?[arraySize];
      nullableuint16Array = new UInt16?[arraySize];
      nullableuint32Array = new UInt32?[arraySize];
      nullableuint64Array = new UInt64?[arraySize];
      nullableint16Array = new Int16?[arraySize];
      nullableint32Array = new Int32?[arraySize];
      nullableint64Array = new Int64?[arraySize];
      nullablefloatArray = new float?[arraySize];
      nullabledoubleArray = new double?[arraySize];
      nullableDateTimeArray = new DateTime?[arraySize];
      nullableDecimalArray = new Decimal?[arraySize];
      nullableOidArray = new Oid?[arraySize];
      listByte = new List<byte>(arraySize); // just samples of what Key can be
      personList = new List<Person>(arraySize);
      petListOidShort = new List<Pet>(arraySize);
      petListLongOid = new List<Pet>(arraySize);
      petList2 = new ArrayList(arraySize);
      int32List = new List<Int32>(arraySize);
      uint32List = new List<UInt32>(arraySize);
      uint64List = new List<ulong>(arraySize);
      oidList = new List<Oid>(arraySize);
      nullableoidList = new List<Oid?>(arraySize);
      personHashSet = new VelocityDbHashSet<Person>();
      person = new Person();
      timeSpan = new TimeSpan(1, 0, 0);
      aPet = new Cat("Boze", 5);
      petListOidShort.Add(aPet);
      petListLongOid.Add(aPet);
      petList2.Add(aPet);
      uint32List.Add(5555);
      int32List.Add(-66666);
      uint64List.Add(8989898988989);
      doubleArray[0] = 0.2323232323232;
      aSlot = new Slot();
      aSlot.value = new Person();
      m_slots = new Slot[5];
      nullableoidList.Add(new Oid((ulong)4444));
      nullableoidList.Add(null);
      nullableoidList.Add(new Oid((ulong)8888));
      if (arraySize > 0)
      {
        oidArray[0] = new Oid((ulong)99999);
        nullableOidArray[0] = new Oid((ulong)99999);
        nullableint32Array[0] = 5;
      }
      if (arraySize > 2)
      {
        oidArray[2] = new Oid((ulong)66666);
        nullableOidArray[2] = new Oid((ulong)66666);
        nullableint32Array[2] = 6;
      }
      for (int i = 0; i < 5; i++)
      {
        m_slots[i].hashCode = i;
        m_slots[i].value = new Person();
        m_slots[i].next = i + 1;
      }
    }
  }

Pet.cs

  [Serializable]
  public class Pet
  {
    string name;
    short age;
    public List<Pet> friends;
    public Pet() { }
    public Pet(string aName, short anAge)
    {
      name = aName;
      age = anAge;
      friends = new List<Pet>(2);
    }

    public string Name
    {
      get
      {
        return name;
      }
      set
      {
        name = value;
      }
    }
  }

Cat.cs

  [Serializable]
  public class Cat : Pet
  {
    public string color;
    public Cat() { } // used by Activator.CreateInstance for non OptimizedPersistable subclasses and value types
    public Cat(string aName, short anAge, string color = "black") : base(aName, anAge)
    {
      this.color = color;
    }
  }

Main Program of AllSupported sample

  class Program
  {
    static readonly string systemDir = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "VelocityDB", "Databases", "AllSupportedSample");
    static void Main(string[] args)
    {
      UInt64 id;
      AllSupported allSupported, allSupported2;
      try
      {
        using (SessionNoServer session = new SessionNoServer(systemDir))
        {
          session.BeginUpdate();
          allSupported = new AllSupported(3);
          session.Persist(allSupported);
          id = allSupported.Id;
         session.Commit();
        }
        using (SessionNoServer session = new SessionNoServer(systemDir))
        {
          session.BeginRead();
          allSupported2 = (AllSupported)session.Open(id);
          session.Commit();
        }
      }
      catch (Exception ex)
      {
        Console.WriteLine(ex.ToString());
      }
    }
  }

Looking at some of the objects created

Shows how to use a BTreeSet and a LINQ query taking advantage of the efficient BTreeSet lookup

using System;
using System.Collections.Generic;
using System.Linq;
using VelocityDb;
using VelocityDb.Session;
using VelocityDb.Collection.BTree;
using VelocityDb.Collection.Comparer;
using VelocityDbSchema.Samples.AllSupportedSample;
using System.IO;

namespace SortedObjects
{
  class SortedObjects
  {
    static readonly string systemDir = "SortedObjects"; // appended to SessionBase.BaseDatabasePath for a full path

    static void Main(string[] args)
    {
      try
      {
        Oid bTreeId;
        bool createOnly = args.Length > 0;
        UInt64 someRandomPersonsIdNumber = 0;
        using (SessionNoServer session = new SessionNoServer(systemDir))
        {
          const UInt32 numberOfPersons = 1000000;
          const ushort nodeMaxSize = 5000;
          const ushort comparisonByteArraySize = sizeof(UInt64); // enough room to hold entire idNumber of a Person
          const bool comparisonArrayIsCompleteKey = true;
          const bool addIdCompareIfEqual = false;
          Person person;
          session.BeginUpdate();
          CompareByField<Person> compareByField = new CompareByField<Person>("idNumber", session, addIdCompareIfEqual);
          BTreeSet<Person> bTree = new BTreeSet<Person>(compareByField, session, nodeMaxSize, comparisonByteArraySize, comparisonArrayIsCompleteKey);
          session.Persist(bTree); // Persist the root of the BTree so that we have something persisted that can be flushed to disk if memory available becomes low
          for (int i = 0; i < numberOfPersons; i++)
          {
            person = new Person();
            if (i % 1000 == 0)
              someRandomPersonsIdNumber = person.IdNumber;
            bTree.AddFast(person);
          }
          bTreeId = bTree.Oid;
          session.Commit();
        }
        if (!createOnly)
          using (SessionNoServer session = new SessionNoServer(systemDir))
          {
            session.BeginRead();
            BTreeSet<Person> bTree = (BTreeSet<Person>)session.Open(bTreeId);
            foreach (Person person in (IEnumerable<Person>)bTree)
            {
              if (person.IdNumber > 196988888791402)
              {
                Console.WriteLine(person);
                break;
              }
            }
            session.Commit();
            session.BeginRead();
            Person lookupPerson = new Person(someRandomPersonsIdNumber);
            UInt64 id = bTree.GetKeyId(lookupPerson); // lookup without opening object having the key field value of someRandomPersonsIdNumber
            Person lookedUpPerson = null;
            bTree.TryGetKey(lookupPerson, ref lookedUpPerson);
            if (id != lookedUpPerson.Id)
              throw new UnexpectedException("Should match");
            // this LINQ statement will trigger a binary search lookup (not a linear serach) of the matching Person objects in the BTreeSet
            Console.WriteLine((from person in bTree where person.IdNumber > 196988888791402 select person).First());
            session.Commit();
          }
      }
      catch (Exception ex)
      {
        Console.WriteLine(ex.ToString());
      }
    }
  }
}

DesEncrypted

  class Program
  {
    const UInt32 desEncryptedStartDatabaseNumber = 10;
    const bool compressPages = true;
    static readonly string systemDir = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "VelocityDB", "Databases", "DesEncrypted");
    static readonly string desEncryptedLocation = System.IO.Path.Combine(systemDir + "desEncryptedLocation");

    static void Main(string[] args)
    {
      try
      {
        using (SessionNoServer session = new SessionNoServer(systemDir))
        {
          DatabaseLocation localLocation = new DatabaseLocation(Dns.GetHostName(), desEncryptedLocation, desEncryptedStartDatabaseNumber, UInt32.MaxValue,
            session, compressPages, PageInfo.encryptionKind.desEncrypted);
          session.BeginUpdate();
          session.NewLocation(localLocation);          
          localLocation.DesKey = Page.StringToByteArray("5d9nndwy"); // Des keys are 8 bytes long
          Person robinHood = new Person("Robin", "Hood", 30);
          Person billGates = new Person("Bill", "Gates", 56, robinHood);
          Person steveJobs = new Person("Steve", "Jobs", 56, billGates);
          robinHood.BestFriend = billGates;
          session.Persist(steveJobs);
          steveJobs.Friends.Add(billGates);
          steveJobs.Friends.Add(robinHood);
          billGates.Friends.Add(billGates);
          robinHood.Friends.Add(steveJobs);
          session.Commit();
        }
        using (SessionNoServer session = new SessionNoServer(systemDir))
        { // Des keys are not persisted in DatabaseLocation (for safety). Instead they are stored as *.des files
          // in the users document directory of the user that created the DatabaseLocation. These files can be copied
          // to other user's document directory when acccess is desired for other users. 
          // Path to user document dir is given by C#: Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
          session.BeginRead();
          Database db = session.OpenDatabase(session.DatabaseNumberOf(typeof(Person)));
          foreach (Page page in db)
          {
            foreach (OptimizedPersistable obj in page)
            {
              Person person = obj as Person;
              if (person != null)
                Console.WriteLine(person.FirstName);
            }
          }
          session.Commit();
        }
      }
      catch (Exception ex)
      {
        Console.WriteLine(ex.ToString());
      }
    }
  }

This sample illustrates the support for changing class definition of persistently stored objects

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using VelocityDb;
using VelocityDb.TypeInfo;
using VelocityDb.Session;
using VelocityDbSchema.Samples.UpdateClass;
using System.IO;
using System.Diagnostics;

namespace UpdateClass
{
  /// <summary>
  /// Test updating a class that already exist in the Database schema, rerun multiple times. Modify class in between runs. Check objects by browsing them with VelocityDbBrowser
  /// </summary>
  public class UpdateClass
  {
    static readonly string systemDir = "UpdateClass";

    static int Main(string[] args)
    {
      try
      {
        UpdatedClass updatedClassObject;
        int ct1 = 0;
        using (SessionNoServer session = new SessionNoServer(systemDir))
        {
          session.BeginUpdate();
          session.UpdateClass(typeof(UpdatedClass)); // call this when you have updated the class since first storing instances of this type or since last call to UpdateClass
          UInt32 dbNum = session.DatabaseNumberOf(typeof(UpdatedClass));
          foreach (UpdatedClass obj in session.AllObjects<UpdatedClass>())
          {
            Console.Write(obj.ToString() + " has members: ");
            foreach (DataMember member in obj.GetDataMembers())
            {
              Console.Write(member.ToString() + " ");
            }
            Console.WriteLine();
            obj.UpdateTypeVersion(); // comment out if you DO NOT want to migrate this object to the latest version of the class
            ct1++;
          }
          int ct2 = 0;
          Database db = session.OpenDatabase(dbNum, true, false);
          if (db != null)
            foreach (UpdatedClass obj in db.AllObjects<UpdatedClass>())
              ct2++;
          Debug.Assert(ct1 == ct2);         
          updatedClassObject = new UpdatedClass();
          session.Persist(updatedClassObject);
          session.Commit();
        }
      }
      catch (Exception ex)
      {
        Console.WriteLine(ex.ToString());
        return 1;
      }
      return 0;
    }
  }
}

Sometimes it is convenient to use LINQ to get data the way you want it. We use it in the IssueTracker that we have online at VelocityDB.com. As you see deploying an asp.net using VelocityDB is easy. The only issue is updating the host and path of DatabaseLocations used.

public ICollection<ProductVersion> AllVersions(string sortExpression)
    {
      try
      {
        string dataPath = HttpContext.Current.Server.MapPath("~/tracker");
        using (SessionNoServer session = new SessionNoServer(dataPath, false, 2000, true, false))
        {
          session.BeginRead();
          IssueTracker bugTracker = (IssueTracker)session.Open(IssueTracker.PlaceInDatabase, 1, 1, false);
          ICollection<ProductVersion> versionSet = bugTracker.VersionSet.Keys;
          if (sortExpression.Length > 0)
          {
            string[] selectAndDir = sortExpression.Split(' ');
            int sorting = int.Parse(selectAndDir[0]);
            bool reverse = selectAndDir.Length > 1;
            switch (sorting)
            {
              case 1: versionSet = (from version in versionSet orderby version.Name select version).ToList();
                break;
              case 2: versionSet = (from version in versionSet orderby version.Description select version).ToList();
                break;
              case 3: versionSet = (from version in versionSet orderby version.ReleaseDate select version).ToList();
                break;
              case 4: versionSet = (from version in versionSet orderby version.CreatedBy select version).ToList();
                break;
            }
            if (reverse)
            {
              List<ProductVersion> tempList = new List<ProductVersion>(versionSet.Count);
              IEnumerable<ProductVersion> temp = versionSet.Reverse<ProductVersion>();
              foreach (ProductVersion issue in temp)
              {
                tempList.Add(issue);
              }
              versionSet = tempList;
            }
          }
          session.Commit();
          return versionSet;
        }
      }
      catch (System.Exception ex)
      {
        this.errorLabel.Text = ex.ToString();
      }
      return null;
    }

Here we import the entire collection of Wikipedia articles/subjects. Wikipedia is available as one giant XML file, the file is 48 GB large (uncompressed). You can download the compressed file (~9 GB) from here. Uncompress it using 7-zip. The import to VelocityDB databases is very fast, it takes about 20 minutes to read, parse and store all 652,870,281 lines of text into 80 structured VelocityDB databases (from & to a spinning disk). The sample program then continues by creating an inverted index of all 14,659,817 Wikipedia articles (782,745,622 lines of XML text), the index is created using parallel threads. All the C# source code for this sample is provided in our download.

Loads World Cities with population from a csv file (~about 2.7 million records) provided by MaxMind. After loading the city data, we attempt to mimic the behavior of QlikView. A ListBoxItem that is selected has a green background, an associated value has a white background and non-associated values have a light gray background. You can select single cells or multiple cells in each column and see how the associations (colors) change. QlikView is a very successful product with revenue around $260 million/year. The product was invented and mostly coded by my fellow Swede, Håkan Wolgé

ImdbImport imports from two compressed text files containing actors, actresses and movie data. The data comes from IMDB


The KeveinBaconNumers application computes the degree of seperation between Kevin Bacon and all other actors and actresses (~ 2 million) taking part in about 350,000 movies.

0 degrees means you are Kevin Bacon

1 degree, you acted in one of Kevin Bacon's movies

2 degrees, you acted in a movie with someone who acted in the same movie as Kevin Bacon

and so on...


The output looks similar to Oracle of Bacon (which by the way is not using an Oracle database!)


[c:\VelocityDb\Release]timer& KevinBaconNumbers.exe& timer

Timer 1 on: 22:29:01

Degree 0 has # of people: 1

Degree 1 has # of people: 3475

Degree 2 has # of people: 385345

Degree 3 has # of people: 894996

Degree 4 has # of people: 121903

Degree 5 has # of people: 7462

Degree 6 has # of people: 446

Degree 7 has # of people: 28

Degree 8 has # of people: 0

Degree 9 has # of people: 0

Timer 1 off: 22:29:28 Elapsed: 0:00:26.94


The entire C# source code for these two applications are part of the download of VelocityDB, download it for free from here.

 

We ran this on a desktop PC, the same one that was used for the triangle counter.


How would you compute this matrix using only SQL code? We bet it wouldn't compute as fast, the entire matrix is calculated in less than half a minute using VelocityDB.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using VelocityDb;
using VelocityDb.Session;

namespace Verify
{
  class Verify
  {
    static int Main(string[] args)
    {
      if (args.Length == 0)
      {
        System.Console.WriteLine("ERROR, no boot path specified. Restart Verify and add bootup database path as a command line parameter");
        return 1;
      }
      int ct = 0;
      try
      {
        using (SessionNoServer session = new SessionNoServer(args[0]))
        {
          DataCache.MaximumMemoryUse = 5000000000; // 5 GB, set this to what fits your case
          session.BeginRead();
          List<Database> dbList = session.OpenAllDatabases();
          foreach (Database db in dbList)
            foreach (Page page in db)
              foreach (IOptimizedPersistable iPers in page)
              {
                object obj = iPers.WrappedObject;
                ++ct;
                if (iPers.WrappedObject is IOptimizedPersistable)
                {
                  UInt64 id = iPers.Id;
                  OptimizedPersistable pObj = iPers as OptimizedPersistable;
                  if (pObj != null)
                  {
                    pObj.LoadFields();
                    foreach (OptimizedPersistable fObj in pObj.OptimizedPersistableFieldValues())
                    {
                      fObj.LoadFields();
                    }
                    foreach (object value in pObj.GetFieldValues())
                    {
                      WeakIOptimizedPersistableReferenceBase weakRef = value as WeakIOptimizedPersistableReferenceBase;
                      if (weakRef != null)
                        if (session.Open(weakRef.Id) == null)
                          throw new UnexpectedException("WeakRefence object is null");
                    }
                  }
                }
                else if (obj is string)
                  continue;
                else if (obj is Array)
                  continue;
                IEnumerable anEnum = obj as IEnumerable;
                if (anEnum != null)
                  foreach (object o in anEnum)
                  {
                  }
              }
          session.Commit();
        }
        Console.WriteLine("OK, verfied " + ct + " objects");
        return 0;
      }
      catch (Exception ex)
      {
        Console.WriteLine("FAILED, verfied " + ct + " objects");
        Console.WriteLine(ex.ToString());
        return -1;
      }
    }
  }
}

Shows how to display persistent objects using an asp TreeView control. We are making the source code public so that you can help us improve the browser. Suggestions are welcome.

This is a mini web crawler that grabs the text from selected web sites and shows which words are used and how frequently. I tried to use teqniques as described in a paper by the Google founders. Did I do it right? Help me out!

The TextIndexer has been extended to also indexing local text files. We downloaded some free complete books from Top 100 - Project Gutenberg

This sample applications imports Baseball statistics data from csv files provided by Sean Lahman

We are including some NUnit tests. These tests should further help explaining how use the VelocityDb API. New NUnit tests are welcome! The NUnit GUI driver is awesome!

There are some good bug tracking software out there but we needed a more complete sample application so we build my own issue (bug) tracking system. Please help us improve this application so that it feels more complete. This application is now included in the sample solution provided with the download of VelocityDB. A live demo of this application is available here.

By working together we can improve the samples. We develop using git as a source control tool. We will setup a repository on GitHub or a similar site until then please email us suggestions and C# sample code. Alternativly, you can use the Isuue tracker and open an issue describing an improvement or a bug. You can attach files to an issue. Email to: Samples@VelocityDB.com

VelocityGraph Sample Applications

This sample shows one way to solve problem descibed here

// This sample shows one way to solve problem descibed in http://stackoverflow.com/questions/28060104/recursive-query-with-sub-graph-aggregation-arbitrary-depth 

using Frontenac.Blueprints;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VelocityDb;
using VelocityDb.Session;
using VelocityGraph;

namespace SupplierTracking
{
  class SupplierTracking
  {
    static readonly string s_systemDir = "SupplierTracking"; // appended to SessionBase.BaseDatabasePath
    static readonly string s_licenseDbFile = "c:/4.odb";

    static int Main(string[] args)
    {
      DataCache.MaximumMemoryUse = 10000000000; // 10 GB, set this to what fits your case
      SupplierTracking supplierTracking = new SupplierTracking();

      using (SessionNoServer session = new SessionNoServer(s_systemDir, 5000, false, true))
      {             
        if (Directory.Exists(session.SystemDirectory))
          Directory.Delete(session.SystemDirectory, true); // remove systemDir from prior runs and all its databases.
        Directory.CreateDirectory(session.SystemDirectory);
        File.Copy(s_licenseDbFile, Path.Combine(session.SystemDirectory, "4.odb"));
        session.BeginUpdate();
        Graph g = new Graph(session);
        session.Persist(g);

        // SCHEMA
        VertexType warehouseVertexType = g.NewVertexType("Warehouse");
        VertexType supplierVertexType = g.NewVertexType("Supplier");
        EdgeType supplierWarehouseEdgeType = g.NewEdgeType("Warehouse", true, supplierVertexType, warehouseVertexType);
        EdgeType moveToS1EdgeType = g.NewEdgeType("MoveS1To", true, warehouseVertexType, warehouseVertexType);
        EdgeType moveToS2EdgeType = g.NewEdgeType("MoveS2To", true, warehouseVertexType, warehouseVertexType);
        EdgeType moveToS3EdgeType = g.NewEdgeType("MoveS3To", true, warehouseVertexType, warehouseVertexType);
        PropertyType supplierNameProperty = supplierVertexType.NewProperty("name", DataType.String, PropertyKind.NotIndexed);
        PropertyType wareHouseNameProperty = warehouseVertexType.NewProperty("name", DataType.String, PropertyKind.NotIndexed);
        PropertyType howManyS1Property = moveToS1EdgeType.NewProperty("howMany", DataType.Integer, PropertyKind.NotIndexed);
        PropertyType howManyS2Property = moveToS2EdgeType.NewProperty("howMany", DataType.Integer, PropertyKind.NotIndexed);
        PropertyType howManyS3Property = moveToS3EdgeType.NewProperty("howMany", DataType.Integer, PropertyKind.NotIndexed);

        Vertex supplier1 = supplierVertexType.NewVertex();
        supplier1.SetProperty(supplierNameProperty, "S1");

        Vertex supplier2 = supplierVertexType.NewVertex();
        supplier2.SetProperty(supplierNameProperty, "S2");

        Vertex supplier3 = supplierVertexType.NewVertex();
        supplier3.SetProperty(supplierNameProperty, "S3");

        Vertex wareHouse1Supplier1 = warehouseVertexType.NewVertex();
        supplier1.AddEdge(supplierWarehouseEdgeType, wareHouse1Supplier1);
        wareHouse1Supplier1.SetProperty(wareHouseNameProperty, "A01");
        Vertex wareHouse2Supplier1 = warehouseVertexType.NewVertex();
        supplier1.AddEdge(supplierWarehouseEdgeType, wareHouse2Supplier1);
        wareHouse2Supplier1.SetProperty(wareHouseNameProperty, "A02");
        Vertex wareHouse3Supplier1 = warehouseVertexType.NewVertex();
        supplier1.AddEdge(supplierWarehouseEdgeType, wareHouse3Supplier1);
        wareHouse3Supplier1.SetProperty(wareHouseNameProperty, "A05");
        Vertex wareHouse4Supplier1 = warehouseVertexType.NewVertex();
        supplier1.AddEdge(supplierWarehouseEdgeType, wareHouse4Supplier1);
        wareHouse4Supplier1.SetProperty(wareHouseNameProperty, "A06");
        Vertex wareHouse1Supplier2 = warehouseVertexType.NewVertex();
        supplier2.AddEdge(supplierWarehouseEdgeType, wareHouse1Supplier2);
        wareHouse1Supplier2.SetProperty(wareHouseNameProperty, "A03");
        Vertex wareHouse2Supplier2 = warehouseVertexType.NewVertex();
        supplier2.AddEdge(supplierWarehouseEdgeType, wareHouse2Supplier2);
        wareHouse2Supplier2.SetProperty(wareHouseNameProperty, "A07");
        Vertex wareHouse1Supplier3 = warehouseVertexType.NewVertex();
        supplier3.AddEdge(supplierWarehouseEdgeType, wareHouse1Supplier3);
        wareHouse1Supplier3.SetProperty(wareHouseNameProperty, "A04");
        Vertex wareHouse2Supplier3 = warehouseVertexType.NewVertex();
        supplier3.AddEdge(supplierWarehouseEdgeType, wareHouse2Supplier3);
        wareHouse2Supplier3.SetProperty(wareHouseNameProperty, "A08");

        Vertex wareHouseB1 = warehouseVertexType.NewVertex();
        wareHouseB1.SetProperty(wareHouseNameProperty, "B01");
        Vertex wareHouseB2 = warehouseVertexType.NewVertex();
        wareHouseB2.SetProperty(wareHouseNameProperty, "B02");
        Vertex wareHouseB3 = warehouseVertexType.NewVertex();
        wareHouseB3.SetProperty(wareHouseNameProperty, "B03");
        Vertex wareHouseB4 = warehouseVertexType.NewVertex();
        wareHouseB4.SetProperty(wareHouseNameProperty, "B04");

        Vertex wareHouseC1 = warehouseVertexType.NewVertex();
        wareHouseC1.SetProperty(wareHouseNameProperty, "C01");
        Vertex wareHouseC2 = warehouseVertexType.NewVertex();
        wareHouseC2.SetProperty(wareHouseNameProperty, "C02");

        Vertex wareHouseD1 = warehouseVertexType.NewVertex();
        wareHouseD1.SetProperty(wareHouseNameProperty, "D01");

        Edge moveA1toB1 = wareHouse1Supplier1.AddEdge(moveToS1EdgeType, wareHouseB1);
        moveA1toB1.SetProperty(howManyS1Property, 750);

        Edge moveA2toB1 = wareHouse2Supplier1.AddEdge(moveToS1EdgeType, wareHouseB1);
        moveA2toB1.SetProperty(howManyS1Property, 500);

        Edge moveA3toB2 = wareHouse1Supplier2.AddEdge(moveToS2EdgeType, wareHouseB2);
        moveA3toB2.SetProperty(howManyS2Property, 750);

        Edge moveA4toB2 = wareHouse1Supplier3.AddEdge(moveToS3EdgeType, wareHouseB2);
        moveA4toB2.SetProperty(howManyS3Property, 500);

        Edge moveA5toB3 = wareHouse3Supplier1.AddEdge(moveToS1EdgeType, wareHouseB3);
        moveA5toB3.SetProperty(howManyS1Property, 100);

        Edge moveA6toB3 = wareHouse4Supplier1.AddEdge(moveToS1EdgeType, wareHouseB3);
        moveA6toB3.SetProperty(howManyS1Property, 200);

        Edge moveA7toB4 = wareHouse2Supplier2.AddEdge(moveToS2EdgeType, wareHouseB4);
        moveA7toB4.SetProperty(howManyS2Property, 50);

        Edge moveA8toB4 = wareHouse2Supplier3.AddEdge(moveToS3EdgeType, wareHouseB4);
        moveA8toB4.SetProperty(howManyS3Property, 450);

        Edge moveB1toC1 = wareHouseB1.AddEdge(moveToS1EdgeType, wareHouseC1);
        moveB1toC1.SetProperty(howManyS1Property, 400);

        Edge moveS2B2toC1 = wareHouseB2.AddEdge(moveToS2EdgeType, wareHouseC1);
        moveS2B2toC1.SetProperty(howManyS2Property, 360);

        Edge moveS3B2toC1 = wareHouseB2.AddEdge(moveToS3EdgeType, wareHouseC1);
        moveS3B2toC1.SetProperty(howManyS3Property, 240);

        Edge moveS1B3toC2 = wareHouseB3.AddEdge(moveToS1EdgeType, wareHouseC2);
        moveS1B3toC2.SetProperty(howManyS1Property, 100);

        Edge moveS2B4toC2 = wareHouseB4.AddEdge(moveToS2EdgeType, wareHouseC2);
        moveS2B4toC2.SetProperty(howManyS2Property, 20);

        Edge moveS3B4toC2 = wareHouseB4.AddEdge(moveToS3EdgeType, wareHouseC2);
        moveS3B4toC2.SetProperty(howManyS3Property, 180);

        Edge moveS1C1toD1 = wareHouseC1.AddEdge(moveToS1EdgeType, wareHouseD1);
        moveS1C1toD1.SetProperty(howManyS1Property, 200);

        Edge moveS2C1toD1 = wareHouseC1.AddEdge(moveToS2EdgeType, wareHouseD1);
        moveS2C1toD1.SetProperty(howManyS2Property, 180);

        Edge moveS3C1toD1 = wareHouseC1.AddEdge(moveToS3EdgeType, wareHouseD1);
        moveS3C1toD1.SetProperty(howManyS3Property, 120);

        Edge moveS1C2toD1 = wareHouseC2.AddEdge(moveToS1EdgeType, wareHouseD1);
        moveS1C2toD1.SetProperty(howManyS1Property, 67);

        Edge moveS2C2toD1 = wareHouseC2.AddEdge(moveToS2EdgeType, wareHouseD1);
        moveS2C2toD1.SetProperty(howManyS2Property, 13);

        Edge moveS3C2toD1 = wareHouseC2.AddEdge(moveToS3EdgeType, wareHouseD1);
        moveS3C2toD1.SetProperty(howManyS3Property, 120);

        Console.WriteLine("Supplier 1 to Warehouse D total: " + supplierTracking.CalculateTotalTo(supplier1, supplierWarehouseEdgeType, moveToS1EdgeType, howManyS1Property, wareHouseD1));
        Console.WriteLine("Supplier 2 to Warehouse D total: " + supplierTracking.CalculateTotalTo(supplier2, supplierWarehouseEdgeType, moveToS2EdgeType, howManyS2Property, wareHouseD1));
        Console.WriteLine("Supplier 3 to Warehouse D total: " + supplierTracking.CalculateTotalTo(supplier3, supplierWarehouseEdgeType, moveToS3EdgeType, howManyS3Property, wareHouseD1));
        g.ExportToGraphJson("c:/SupplierTrackingExportToGraphJson.json");
        Graph g2 = new Graph(session);
        session.Persist(g2);
        g2.ImportGraphJson("c:/SupplierTrackingExportToGraphJson.json");
        session.Commit();
        return 0;
      }
    }

    int CalculateTotalTo(Vertex supplier, EdgeType supplierWarehouseEdgeType, EdgeType moveToEdgeType, PropertyType howManyProperty, Vertex toVertex)
    {
      int total = 0;
      HashSet<Vertex> excludeSet = new HashSet<Vertex>();
      foreach (IEdge wareHouseEdge in supplier.GetEdges(supplierWarehouseEdgeType, Direction.Out))
      {
        Vertex supplierWareHouse = (Vertex)wareHouseEdge.GetVertex(Direction.In);
        var allPaths = supplierWareHouse.Traverse(toVertex, moveToEdgeType, 10, true, null, excludeSet);
        foreach (List<Edge> path in allPaths)
        {
          if (path.Count > 0)
            total += (int)path.Last().GetProperty(howManyProperty); // last because that is all we care about in this simplified sample
          foreach (Edge edge in path)
          {
            excludeSet.Add(edge.Tail);
          }
        }
      }
      return total;
    }
  }
}

This sample is a preview of VelocityGraph, help us define the best possible graph api! The start of this api is inspired by Sparksee, the sample here mimics what the Sparksee sample is doing. Unlike Sparksee, which is a C++/C implemented api, VelocityGraph is all implemented in C# and enable any type of Element values. VelocityGraph is provided as open source on GitHub, https://github.com/VelocityDB/VelocityDB/tree/master/VelocityGraph. and implements the graph API Blueprints standard interfaces as provided in Frontenac Blueprints. Anyone is welcome to contribute! VelocityGraph is built on top of VelocityDB. You will need a VelocityDB license to use VelocityGraph.

using System;
using System.IO;
using System.Linq;
using VelocityDb.Session;
using VelocityGraph;

namespace VelocityGraphSample
{
  using Frontenac.Blueprints;
  using System.Collections.Generic;
  class VelocityGraphSample
  {
    static readonly string systemDir = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
      "VelocityDB" + Path.DirectorySeparatorChar + "Databases" + Path.DirectorySeparatorChar + "VelocityGraphSample");

    static void Main(string[] args)
    {
      if (Directory.Exists(systemDir))
        Directory.Delete(systemDir, true); // remove systemDir from prior runs and all its databases.

      using (ServerClientSession session = new ServerClientSession(systemDir, System.Net.Dns.GetHostName()))
      {
        session.BeginUpdate();
        Graph g = new Graph(session);
        session.Persist(g);

        // SCHEMA
        // Add a node type for the movies, with a unique identifier and two indexed Propertys
        VertexType movieType = g.NewVertexType("MOVIE");
        PropertyType movieTitleType = g.NewVertexProperty(movieType, "TITLE", DataType.String, PropertyKind.Indexed);
        PropertyType movieYearType = g.NewVertexProperty(movieType, "YEAR", DataType.Integer, PropertyKind.Indexed);

        // Add a node type for the people, with a unique identifier and an indexed Property
        VertexType peopleType = g.NewVertexType("PEOPLE");
        PropertyType peopleNameType = g.NewVertexProperty(peopleType, "NAME", DataType.String, PropertyKind.Indexed);

        // Add an undirected edge type with a Property for the cast of a movie
        EdgeType castType = g.NewEdgeType("CAST", false);
        PropertyType castCharacterType = g.NewEdgeProperty(castType, "CHARACTER", DataType.String, PropertyKind.Indexed);

        // Add a directed edge type restricted to go from people to movie for the director of a movie
        EdgeType directsType = g.NewEdgeType("DIRECTS", true, peopleType, movieType);

        // DATA
        // Add some MOVIE nodes

        Vertex mLostInTranslation = movieType.NewVertex();
        mLostInTranslation.SetProperty(movieTitleType, "Lost in Translation");
        mLostInTranslation.SetProperty(movieYearType, (int)2003);

        Vertex mVickyCB = movieType.NewVertex();
        mVickyCB.SetProperty(movieTitleType, "Vicky Cristina Barcelona");
        mVickyCB.SetProperty(movieYearType, (int)2008);

        Vertex mManhattan = movieType.NewVertex();
        mManhattan.SetProperty(movieTitleType, "Manhattan");
        mManhattan.SetProperty(movieYearType, (int)1979);

        // Add some PEOPLE nodes
        Vertex pScarlett = peopleType.NewVertex();
        pScarlett.SetProperty(peopleNameType, "Scarlett Johansson");

        Vertex pBill = peopleType.NewVertex();
        pBill.SetProperty(peopleNameType, "Bill Murray");

        Vertex pSofia = peopleType.NewVertex();
        pSofia.SetProperty(peopleNameType, "Sofia Coppola");

        Vertex pWoody = peopleType.NewVertex();
        pWoody.SetProperty(peopleNameType, "Woody Allen");

        Vertex pPenelope = peopleType.NewVertex();
        pPenelope.SetProperty(peopleNameType, "Penélope Cruz");

        Vertex pDiane = peopleType.NewVertex();
        pDiane.SetProperty(peopleNameType, "Diane Keaton");

        // Add some CAST edges
        Edge anEdge;
        anEdge = g.NewEdge(castType, mLostInTranslation, pScarlett);
        anEdge.SetProperty(castCharacterType, "Charlotte");

        anEdge = g.NewEdge(castType, mLostInTranslation, pBill);
        anEdge.SetProperty(castCharacterType, "Bob Harris");

        anEdge = g.NewEdge(castType, mVickyCB, pScarlett);
        anEdge.SetProperty(castCharacterType, "Cristina");

        anEdge = g.NewEdge(castType, mVickyCB, pPenelope);
        anEdge.SetProperty(castCharacterType, "Maria Elena");

        anEdge = g.NewEdge(castType, mManhattan, pDiane);
        anEdge.SetProperty(castCharacterType, "Mary");

        anEdge = g.NewEdge(castType, mManhattan, pWoody);
        anEdge.SetProperty(castCharacterType, "Isaac");

        // Add some DIRECTS edges
        anEdge = g.NewEdge(directsType, pSofia, mLostInTranslation);
        anEdge = g.NewEdge(directsType, pWoody, mVickyCB);
        anEdge = g.NewEdge(directsType, pWoody, mManhattan);

        // QUERIES
        // Get the movies directed by Woody Allen
        Dictionary<Vertex, HashSet<Edge>> directedByWoody = pWoody.Traverse(directsType, Direction.Out);

        // Get the cast of the movies directed by Woody Allen
        Dictionary<Vertex, HashSet<Edge>> castDirectedByWoody = g.Traverse(directedByWoody.Keys.ToArray(), castType, Direction.Both);

        // Get the movies directed by Sofia Coppola
        Dictionary<Vertex, HashSet<Edge>> directedBySofia = pSofia.Traverse(directsType, Direction.Out);

        // Get the cast of the movies directed by Sofia Coppola
        Dictionary<Vertex, HashSet<Edge>> castDirectedBySofia = g.Traverse(directedBySofia.Keys.ToArray(), castType, Direction.Both);

        // We want to know the people that acted in movies directed by Woody AND in movies directed by Sofia.
        IEnumerable<Vertex> castFromBoth = castDirectedByWoody.Keys.Intersect(castDirectedBySofia.Keys);

        // Say hello to the people found
        foreach (Vertex person in castFromBoth)
        {
          object value = person.GetProperty(peopleNameType);
          System.Console.WriteLine("Hello " + value);
        }

        var billM = g.Traverse(directedBySofia.Keys.ToArray(), castType, Direction.Both).Keys.Where(vertex => vertex.GetProperty(peopleNameType).Equals("Bill Murray"));

        // Say hello to Bill Murray
        foreach (Vertex person in billM)
        {
          object value = person.GetProperty(peopleNameType);
          System.Console.WriteLine("Hello " + value);
        }

        session.Commit();
      }

      using (ServerClientSession session = new ServerClientSession(systemDir, System.Net.Dns.GetHostName()))
      {
        session.BeginRead();
        Graph g = Graph.Open(session);
        VertexType movieType = g.FindVertexType("MOVIE");
        PropertyType movieTitleProperty = g.FindVertexProperty(movieType, "TITLE");
        Vertex obj = g.FindVertex(movieTitleProperty, "Manhattan");
        session.Commit();
      }
    }
  }
}
/*
Social graph test
http://odysseas.calit2.uci.edu/doku.php/public:online_social_networks#facebook_social_graph_-_breadth_first_search

Contains a set of unique users on Facebook, and all the userids of their friends. Can be used as a good example for finding shortest path queries.
queries:
- Find Shortest path between two given user ids
- Get all the paths between two user ids
- Get the number of unique 2nd level friends a given user has (friends of my friends)
- Get the top 10 users with most friends
*/

using Frontenac.Blueprints;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using VelocityDb;
using VelocityDb.Session;
using VelocityGraph;

namespace FacebookGraph
{
  class FacebookGraph
  {
    static readonly string systemDir = "FacebookGraph";
    static readonly string inputData = "D:/bfs-28-socialgraph-release-corrected"; // change if you need to, download dataset from http://www.VelocityDB.com/Public/bfs-28-socialgraph-release-corrected.zip (and uncompress with 7-zip http://www.7-zip.org/)
    //static readonly string inputData = "D:\\bfs-28-socialgraph-release";// change if you need to, download dataset from http://odysseas.calit2.uci.edu/doku.php/public:online_social_networks#facebook_social_graph_-_breadth_first_search
    static readonly string licenseDbFile = "D:/4.odb";
    enum Gender { Male, Female, Unknown };

    static void Main(string[] args)
    {
      DataCache.MaximumMemoryUse = 27000000000; // 27 GB, set this to what fits your case
      FacebookGraph facebookGraph = new FacebookGraph();
      //SessionBase.BaseDatabasePath = "d:/Databases";
      bool import = args.Length > 0 && args[0].ToLower() == "-import";
      bool dirExist = Directory.Exists(Path.Combine(SessionBase.BaseDatabasePath, systemDir));
      if (import || !dirExist)
        facebookGraph.ingestData();
      facebookGraph.doQueries();
    }

    public void ingestData()
    {
      if (Directory.Exists(Path.Combine(SessionBase.BaseDatabasePath, systemDir)))
        Directory.Delete(Path.Combine(SessionBase.BaseDatabasePath, systemDir), true); // remove systemDir from prior runs and all its databases.
      Directory.CreateDirectory(Path.Combine(SessionBase.BaseDatabasePath, systemDir));
      File.Copy(licenseDbFile, Path.Combine(SessionBase.BaseDatabasePath, systemDir, "4.odb"));

      using (SessionNoServer session = new SessionNoServer(systemDir, false, 5000, false, true))
      {
        session.BeginUpdate();
        session.DefaultDatabaseLocation().CompressPages = false;
        Graph g = new Graph(session);
        session.Persist(g);

        // SCHEMA
        VertexType userType = g.NewVertexType("User");

        EdgeType friendEdgeType = g.NewEdgeType("Friend", true, userType, userType);

        PropertyType countryProperty = userType.NewProperty("country", DataType.String, PropertyKind.NotIndexed);

        PropertyType incomeProperty = userType.NewProperty("income", DataType.Long, PropertyKind.NotIndexed);

        PropertyType friendshipStartProperty = friendEdgeType.NewProperty("start", DataType.DateTime, PropertyKind.NotIndexed);

        // DATA
        int lineNumber = 0;
        long fiendsCt = 0;
        int stop = (int)Math.Pow(2, 26); // make sure to create enough of these
        for (int i = 1; i < stop; i++)
          userType.NewVertex();
        session.Commit();
        session.BeginUpdate();
        foreach (string line in File.ReadLines(inputData))
        {
          if (++lineNumber % 10000 == 0)
            Console.WriteLine("Parsing user " + lineNumber + ", friends total: " + fiendsCt + " at " + DateTime.Now);
          string[] fields = line.Split(' ');
          Vertex aUser = null;
          foreach (string s in fields)
          {
            if (s.Length > 0)
            {
              if (aUser == null)
                aUser = new Vertex(g, userType, int.Parse(s));
              else
              {
                ++fiendsCt;
                Vertex aFriend = new Vertex(g, userType, int.Parse(s));
                if (fiendsCt % 2 == 0)
                  aFriend.SetProperty(countryProperty, "Sweden"); // just some random stuff
                else
                  aFriend.SetProperty(incomeProperty, fiendsCt); // just some random stuff
                Edge edge = friendEdgeType.NewEdge(aUser, aFriend);
                if (fiendsCt % 2 == 0)
                  edge.SetProperty(friendshipStartProperty, DateTime.Now);
              }
            }
          }
          if (DataCache.MaximumMemoryUse >= 27000000000)
          {
            if (lineNumber >= 120000) // remove this condition if you have time to wait a while...
              break;
          }
          else if (lineNumber >= 60000)
            break;
        }
        Console.WriteLine("Done importing " + lineNumber + " users with " + fiendsCt + " friends");
        session.Commit();
      }
    }

    // Queries
    public void doQueries()
    {
      using (SessionNoServer session = new SessionNoServer(systemDir, false))
      {
        session.BeginRead();
        Graph g = Graph.Open(session); // it takes a while to open graph fresh from databases
        VertexType userType = g.FindVertexType("User");
        EdgeType friendEdgeType = g.FindEdgeType("Friend");
        PropertyType countryProperty = userType.FindProperty("country");
        PropertyType incomeProperty = userType.FindProperty("income");
        PropertyType friendshipStartProperty = friendEdgeType.FindProperty("start");

        Vertex someUser = userType.GetVertex(1);
        Vertex someUser2 = userType.GetVertex(12282);

        var someUserFriends = from Edge e in someUser.GetEdges(friendEdgeType, Direction.Out)
                              select e.Head;
        HashSet<Edge> edges = new HashSet<Edge>();
        Edge edge = (Edge)someUser.GetEdges(friendEdgeType, Direction.Out).Skip(1).First();
        edges.Add(edge);
        // Find Shortest path between two given user ids
        List<List<Edge>> path = someUser.Traverse(someUser2, friendEdgeType, 10, false);
        Debug.Assert(path.Count > 0);
        var path2 = someUser.Traverse(userType.GetVertex(41), friendEdgeType, 10, false);
        HashSet<Vertex> vertices = new HashSet<Vertex>();
        vertices.Add(someUser2);
        var path3 = someUser.Traverse(userType.GetVertex(2876), friendEdgeType, 10, false, vertices); // path must include vertices
        var path3b = someUser.Traverse(userType.GetVertex(2876), friendEdgeType, 10, false, null, vertices); // path must NOT include vertices
        var path3c = someUser.Traverse(userType.GetVertex(2876), friendEdgeType, 10, false, null, null, edges); // path must include edges
        var path3d = someUser.Traverse(userType.GetVertex(2876), friendEdgeType, 10, false, null, null, null, edges); // path must NOT include edges
        HashSet<PropertyType> vertexPropertyTypes = new HashSet<PropertyType>();
        vertexPropertyTypes.Add(incomeProperty);
        vertexPropertyTypes.Add(countryProperty);
        var path3e = someUser.Traverse(userType.GetVertex(2876), friendEdgeType, 10, false, null, null, null, edges, vertexPropertyTypes); // path must NOT include edges and at least one vertex in path must have property in propertyTypes
        var path3f = someUser.Traverse(userType.GetVertex(2876), friendEdgeType, 10, false, null, null, null, edges, null, vertexPropertyTypes); // path must NOT include edges and no vertex in path must have any property in propertyTypes
        HashSet<PropertyType> edgePropertyTypes = new HashSet<PropertyType>();
        edgePropertyTypes.Add(friendshipStartProperty);
        var path3g = someUser.Traverse(userType.GetVertex(2876), friendEdgeType, 10, false, null, null, null, edges, null, null, edgePropertyTypes);
        var path3h = someUser.Traverse(userType.GetVertex(2876), friendEdgeType, 10, false, null, null, null, edges, null, null, null, edgePropertyTypes);
        var path3i = someUser.Traverse(userType.GetVertex(2876), friendEdgeType, 10, false, null, null, null, edges, null, null, null, null, p => { object pv = p.GetProperty(countryProperty); return pv != null && pv.Equals("Sweden"); });
        var path3j = someUser.Traverse(userType.GetVertex(2876), friendEdgeType, 10, false, null, null, null, edges, null, null, null, null, null, p => { DateTime? pv = (DateTime?)p.GetProperty(friendshipStartProperty); return pv != null && pv.Value.CompareTo(DateTime.Now) > 0; });
        var path4 = someUser.Traverse(userType.GetVertex(2798), friendEdgeType, 10, false);
        var path5 = someUser.Traverse(userType.GetVertex(175), friendEdgeType, 10, false);
        var path6 = someUser.Traverse(userType.GetVertex(1531), friendEdgeType, 10, false);
        var path7 = someUser.Traverse(userType.GetVertex(1537), friendEdgeType, 10, false);
        Console.WriteLine();

        // Get all the paths between two user ids
        var path8 = someUser.Traverse(someUser2, friendEdgeType, 10, true);
        path = someUser.Traverse(userType.GetVertex(41), friendEdgeType, 10, true);

        // Get the number of unique 2nd level friends a given user has (friends of my friends)

        var someUsers2ndLevelFriends = (from v in someUserFriends
                                        from Edge e in v.GetEdges(friendEdgeType, Direction.Out)
                                        select e.Head).Distinct();

        Console.WriteLine("unique 2nd level friends a given user has");
        int ct = 0;
        foreach (Vertex v in someUsers2ndLevelFriends)
        {
          if (++ct % 100 == 0)
            Console.WriteLine("User id: " + v.VertexId);
        }
        Console.WriteLine("Some user has: " + ct + " 2nd level friends");
        Console.WriteLine();

        // Get the top 10 users with most friends
        var top10mostFriends = from vertex in userType.GetTopNumberOfEdges(friendEdgeType, 10, Direction.Out)
                               select vertex;
        Console.WriteLine("top 10 users with most friends");
        foreach (Vertex v in top10mostFriends)
        {
          long count = v.GetNumberOfEdges(friendEdgeType, Direction.Out);
          Console.WriteLine("User id: " + v.VertexId + "\t number of friends: " + count);
        }
        Console.WriteLine();
        session.Commit();
      }
    }
  }
}
/*
Dating Recommendations
http://www.occamslab.com/petricek/data/

Dating site with ratings. Can be used to recommend other people a user might like.
17 million ratings, 168 000 profiles that are rated by 135 000 users.

Complex queries
-    Given a user id, and based on the rated profiles, find other users who have rated similarly on the same profiles, and find other profiles to recommend based on what those other users have rated
-    Get all female users with less than 50 ratings
-    Get all male users with at least one 10 rating
-    Get the first 10 male users who have rated at least 3 of the same profiles as the given user.

Statistics queries
-    Get the 20 profiles with the most ratings
-    Get the 20 best rated profiles regardless of gender
-    Get the 20 best rated males
-    Get the 20 best rated females
*/

using System;
using System.IO;
using System.Linq;
using VelocityDb.Session;
using VelocityGraph;
using Frontenac.Blueprints;
using System.Collections.Generic;
using VelocityDb;

namespace DatingRecommendations
{

  class DatingRecommendations
  {
    static readonly string s_systemDir = SessionBase.BaseDatabasePath + "/DatingRecommendations";
    static readonly string s_inputDataDir = "D:/libimseti"; // change if you need to, download dataset from http://www.occamslab.com/petricek/data/
    static readonly string s_licenseDbFile = "c:/4.odb";
    static readonly int s_highestRating = 10;
    enum Gender { Male, Female, Unknown };

    static void Main(string[] args)
    {
      bool import = args.Length > 0 && args[0].ToLower() == "-import";
      bool dirExist = Directory.Exists(s_systemDir);
      if (import || !dirExist)
      {
        if (dirExist)
          Directory.Delete(s_systemDir, true); // remove systemDir from prior runs and all its databases.
        Directory.CreateDirectory(s_systemDir);
        File.Copy(s_licenseDbFile, Path.Combine(s_systemDir, "4.odb"));
        using (SessionNoServer session = new SessionNoServer(s_systemDir))
        {
          DataCache.MaximumMemoryUse = 12000000000; // 12 GB, set this to what fits your case
          SessionBase.BTreeAddFastTransientBatchSize = 10; // reduces memory usage
          Vertex[] ratingVertices = new Vertex[10];
          session.BeginUpdate();
          session.DefaultDatabaseLocation().CompressPages = PageInfo.compressionKind.LZ4;
          Graph g = new Graph(session);
          session.Persist(g);

          // SCHEMA
          VertexType userType = g.NewVertexType("User");
          PropertyType genderType = userType.NewProperty("Gender", DataType.Integer, PropertyKind.Indexed);

          VertexType ratingType = g.NewVertexType("Rating");
          PropertyType ratingValuePropertyType = ratingType.NewProperty("RatingValue", DataType.Integer, PropertyKind.Indexed);

          EdgeType ratingEdgeType = g.NewEdgeType("UserToRating", true, userType, ratingType);

          EdgeType ratingOfType = g.NewEdgeType("RatingOf", false, userType, userType);
          PropertyType ratingEdgePropertyType = ratingOfType.NewProperty("Rating", DataType.Integer, PropertyKind.Indexed);

          // DATA
          using (FileStream stream = File.OpenRead(System.IO.Path.Combine(s_inputDataDir, "gender.dat")))
          {
            using (StreamReader file = new System.IO.StreamReader(stream))
            {
              string line;
              int lineNumber = 0;
              while ((line = file.ReadLine()) != null)
              {
                lineNumber++;
                string[] fields = line.Split(',');
                Vertex aUser = userType.NewVertex();
                aUser.SetProperty(genderType, (int)fields[1][0] == 'M' ? Gender.Male : fields[1][0] == 'F' ? Gender.Female : Gender.Unknown);
              }
              Console.WriteLine("Done importing " + lineNumber + " users");
            }
          }

          using (FileStream stream = File.OpenRead(System.IO.Path.Combine(s_inputDataDir, "ratings.dat")))
          {
            using (StreamReader file = new System.IO.StreamReader(stream))
            {
              string line;
              int lineNumber = 0;
              Vertex rater = null;
              int raterId;
              int priorRaterId = -1;

              while ((line = file.ReadLine()) != null)
              {
                lineNumber++;
                if (lineNumber % 1000000 == 0)
                  Console.WriteLine("Parsing rating # " + lineNumber);
                string[] fields = line.Split(',');
                raterId = int.Parse(fields[0]);
                if (raterId != priorRaterId)
                  rater = userType.GetVertex(raterId);
                priorRaterId = raterId;
                int ratedId = int.Parse(fields[1]);
                int rating = int.Parse(fields[2]);
                Vertex ratingVertex = ratingVertices[rating - 1];
                if (ratingVertex == null)
                {
                  ratingVertex = ratingType.NewVertex();
                  ratingVertex.SetProperty(ratingValuePropertyType, rating);
                  ratingVertices[rating - 1] = ratingVertex;
                }
                Vertex rated = userType.GetVertex(ratedId);
                Edge aRatingOf = ratingOfType.NewEdge(rater, rated);
                aRatingOf.SetProperty(ratingEdgePropertyType, rating);
                Edge userRating = ratingEdgeType.NewEdge(rated, ratingVertex);
              }
              Console.WriteLine("Done importing " + lineNumber + " ratings");
            }
          }
          session.Commit();
        }
      }
      // Query
      using (SessionNoServer session = new SessionNoServer(s_systemDir))
      {
        session.BeginRead();
        Graph g = Graph.Open(session);
        VertexType userType = g.FindVertexType("User");
        PropertyType genderType = userType.FindProperty("Gender");

        VertexType ratingType = g.FindVertexType("Rating");
        PropertyType ratingValuePropertyType = ratingType.FindProperty("RatingValue");

        EdgeType ratingEdgeType = g.FindEdgeType("UserToRating");

        EdgeType ratingOfType = g.FindEdgeType("RatingOf");
        PropertyType ratingEdgePropertyType = ratingOfType.FindProperty("Rating");
        // Complex queries
        int ct = 0;

// Given a user id, and based on the rated profiles, find other users who have rated similarly on the same profiles, and find other profiles to recommend based on what those other users have rated
        Vertex someUser = userType.GetVertex(1);
        var similarRatings = (from Edge e in someUser.GetEdges(ratingOfType, Direction.Out)
                              from Edge edge in e.Head.GetEdges(ratingOfType, Direction.Out)
                              where someUser != edge.Head
                              where ((int)e.GetProperty(ratingEdgePropertyType) == (int)edge.GetProperty(ratingEdgePropertyType))
                              select edge.Tail).Distinct();

        var someUserRated = from Edge e in someUser.GetEdges(ratingOfType, Direction.Out)
                            select e.Head;

        var recommendedProfles = from v in similarRatings
                                 from Edge e in v.GetEdges(ratingOfType, Direction.Out)
                                 where someUserRated.Contains(e.Head) == false
                                 select e.Head;

        Console.WriteLine("Some user's rated profiles");
        ct = 0;
        foreach (Vertex v in someUserRated)
        {
          if (ct++ % 50 == 0) // don't print them all !
            Console.WriteLine("User id: " + v.VertexId);
        }
        Console.WriteLine("Number of some user's rated profiles: " + ct);

        Console.WriteLine("Given a user id, and based on the rated profiles, find other users who have rated similarly on the same profiles");
        ct = 0;
        foreach (Vertex v in similarRatings)
        {
          if (ct++ % 50 == 0) // don't print them all !
            Console.WriteLine("User id: " + v.VertexId);
        }
        Console.WriteLine("Number of matching profiles: " + ct);

        Console.WriteLine("Given a user id, and based on the rated profiles, find other users who have rated similarly on the same profiles, and find other profiles to recommend based on what those other users have rated");
        ct = 0;
        foreach (Vertex v in recommendedProfles)
        {
          if (ct++ % 5000 == 0) // don't print them all !
            Console.WriteLine("User id: " + v.VertexId);
        }
        Console.WriteLine("Number of matching profiles: " + ct);

// Get all female users with less than 50 ratings
        Console.WriteLine();
        var females = from u in userType.GetVertices()
                      where ((Gender)u.GetProperty(genderType)) == Gender.Female
                      select u;
        var femalesLess50Ratings = from f in females
                                   where f.GetNumberOfEdges(ratingEdgeType, Direction.Out) < 50
                                   select f;
        Console.WriteLine("Female users with less than 50 ratings");
        ct = 0;
        foreach (Vertex f in femalesLess50Ratings)
        {
          long count = f.GetNumberOfEdges(ratingEdgeType, Direction.Out);
          if (ct++ % 5000 == 0) // don't print them all !
            Console.WriteLine("User id: " + f.VertexId + "\tnumber of ratings: " + count);
        }
        Console.WriteLine("Number of females with fewer than 50 ratings: " + ct);
        Console.WriteLine();

// Get all male users with at least one 10 rating
        Console.WriteLine();
        var rated10vertex = (from v in ratingType.GetVertices()
                             where ((int)v.GetProperty(ratingValuePropertyType)) == 10
                             select v).First();

        var rated10 = (from e in rated10vertex.GetEdges(ratingEdgeType, Direction.In)
                       select e.GetVertex(Direction.Out)).Distinct();

        var rated10male = from Vertex v in rated10
                          where ((Gender)v.GetProperty(genderType)) == Gender.Male
                          select v;

        Console.WriteLine("Males with at least one 10 rating");
        ct = 0;
        foreach (Vertex v in rated10male)
        {
          if (ct++ % 5000 == 0) // don't print them all !
            Console.WriteLine("User id: " + v.VertexId);
        }
        Console.WriteLine("Number of males with at least one 10 rating: " + ct);
        Console.WriteLine();

// Get the first 10 male users who have rated at least 3 of the same profiles as the given user.
        Console.WriteLine("10 male users who have rated at least 3 of the same profiles as the given user");
        var males = from u in userType.GetVertices()
                    where ((Gender)u.GetProperty(genderType)) == Gender.Male
                    select u;

        var someUserHasRated = from Edge o in someUser.GetEdges(ratingOfType, Direction.Out)
                               select o.Head;

        var first10withSame3ratedAs = from m in males
                                      where (from Edge r in m.GetEdges(ratingOfType, Direction.Out) select r.Head).Intersect(someUserHasRated).ToArray().Length >= 3
                                      select m;
        ct = 0;
        foreach (Vertex v in first10withSame3ratedAs)
        {
          if (++ct > 10)
            break;
          Console.WriteLine("User id: " + v.VertexId);
        }
        Console.WriteLine();

        // Statistical queries
// Get the 20 profiles with the most ratings
        var top20mostRatings = (from v in userType.GetVertices()
                               orderby v.GetNumberOfEdges(ratingEdgeType, Direction.Out) descending
                               select v).Take(20);
        Console.WriteLine("20 profiles with the most ratings");
        ct = 0;
        foreach (Vertex v in top20mostRatings)
        {
          int count = (int)v.GetNumberOfEdges(ratingEdgeType, Direction.Out);  
          Console.WriteLine("User id: " + v.VertexId + "\tnumber of ratings: " + count);
        }
        Console.WriteLine();

        var ratingsVertexEnum = from v in ratingType.GetVertices() orderby v.GetProperty(ratingValuePropertyType) descending select v;
        Vertex rating10Vertex = ratingsVertexEnum.First();
// Get the 20 best rated profiles regardless of gender
        var top = from u in userType.GetVertices()
                  let edgeCt = u.GetNumberOfEdges(ratingEdgeType, rating10Vertex, Direction.Out)
                  orderby edgeCt descending
                  select new { u, edgeCt };
                   
        Console.WriteLine("20 best rated profiles regardless of gender");
        ct = 0;
        foreach (var v in top)
        {
          if (++ct > 20)
            break;
          Console.WriteLine("User id: " + v.u.VertexId + "\t10 ratings: " + v.edgeCt);
        }
        Console.WriteLine();

// Get the 20 best rated males
        Console.WriteLine("20 best rated male profiles");
        var top20males = from u in userType.GetVertices()
                         where ((Gender)u.GetProperty(genderType)) == Gender.Male
                         let edgeCt = u.GetNumberOfEdges(ratingEdgeType, rating10Vertex, Direction.Out)
                         orderby edgeCt descending
                         select new { u, edgeCt };

        ct = 0;
        foreach (var v in top20males)
        {
          if (++ct > 20)
            break;
          Console.WriteLine("Male User id: " + v.u.VertexId + " \t10 ratings: " + v.edgeCt);
        }
        Console.WriteLine();

// Get the 20 best rated females
        Console.WriteLine("20 best rated female profiles");
        var top20females = from u in userType.GetVertices()
                           where ((Gender)u.GetProperty(genderType)) == Gender.Female
                           let edgeCt = u.GetNumberOfEdges(ratingEdgeType, rating10Vertex, Direction.Out)
                           orderby edgeCt descending
                           select new { u, edgeCt };
        ct = 0;
        foreach (var v in top20females)
        {
          if (++ct > 20)
            break;
          Console.WriteLine("Female User id: " + v.u.VertexId + "\t10 ratings: " + v.edgeCt);
        }
        session.Commit();
      }
    }
  }
}