context: // --------------------------------------------------------------------------------------------------------------------
  // <copyright file="Load.cs" company="Allors bvba">
  //   Copyright 2002-2016 Allors bvba.
  // Dual Licensed under
  //   a) the Lesser General Public Licence v3 (LGPL)
  //   b) the Allors License
  // The LGPL License is included in the file lgpl.txt.
  // The Allors License is an addendum to your contract.
  // Allors Platform is distributed in the hope that it will be useful,
  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  // GNU General Public License for more details.
  // For more information visit http://www.allors.com/legal
  // </copyright>
  // --------------------------------------------------------------------------------------------------------------------
  
  using System.Linq;
  
  namespace Allors.Adapters.Object.SqlClient
  {
      using System;
      using System.Collections.Generic;
      using System.Data;
      using System.Data.SqlClient;
      using System.Xml;
  
      using Adapters;
  
      using Allors.Meta;
  
      internal class Load
      {
          private static readonly byte[] EmptyByteArray = new byte[0];
  
          private readonly Database database;
          private readonly ObjectNotLoadedEventHandler objectNotLoaded;
          private readonly RelationNotLoadedEventHandler relationNotLoaded;
          private readonly XmlReader reader;
  
          private readonly Dictionary<long, IObjectType> objectTypeByObjectId;
          private readonly Dictionary<long, long> objectVersionByObjectId;
  
          private readonly Dictionary<IRelationType, Dictionary<long, long>> associationIdByRoleIdByRelationTypeId;
          private readonly Dictionary<IRelationType, Dictionary<long, object>> roleByAssociationIdByRelationTypeId;
          private string tableName;
  
          internal Load(Database database, ObjectNotLoadedEventHandler objectNotLoaded, RelationNotLoadedEventHandler relationNotLoaded, XmlReader reader)
          {
              this.database = database;
              this.objectNotLoaded = objectNotLoaded;
              this.relationNotLoaded = relationNotLoaded;
              this.reader = reader;
  
              this.objectTypeByObjectId = new Dictionary<long, IObjectType>();
              this.objectVersionByObjectId = new Dictionary<long, long>();
  
              this.associationIdByRoleIdByRelationTypeId = new Dictionary<IRelationType, Dictionary<long, long>>();
              this.roleByAssociationIdByRelationTypeId = new Dictionary<IRelationType, Dictionary<long, object>>();
          }
  
          internal void Execute()
          {
              this.Read();
  
              this.database.Init();
  
              using (var connection = new SqlConnection(this.database.ConnectionString))
              {
                  try
                  {
                      connection.Open();
  
                      this.WriteObjectsTable(connection);
  
                      this.WriteObjectTables(connection);
  
                      this.WriteRelationTables(connection);
  
                      connection.Close();
                  }
                  catch (Exception e)
                  {
                      try
                      {
                          connection.Close();
                      }
                      finally
                      {
                          this.database.Init();
                          throw e;
                      }
                  }
              }
          }
  
          private bool Read()
          {
              while (this.reader.Read())
              {
                  // only process elements, ignore others
                  if (this.reader.NodeType.Equals(XmlNodeType.Element))
                  {
                      if (this.reader.Name.Equals(Serialization.Population))
                      {
                          Serialization.CheckVersion(this.reader);
  
                          if (!this.reader.IsEmptyElement)
                          {
                              this.ReadPopulation();
                          }
  
                          return true;
                      }
                  }
              }
              return false;
          }
  
          private void ReadPopulation()
          {
              while (this.reader.Read())
              {
                  switch (this.reader.NodeType)
                  {
                      // only process elements, ignore others
                      case XmlNodeType.Element:
                          if (this.reader.Name.Equals(Serialization.Objects))
                          {
                              if (!this.reader.IsEmptyElement)
                              {
                                  this.ReadObjects();
                              }
                          }
                          else if (this.reader.Name.Equals(Serialization.Relations))
                          {
                              if (!this.reader.IsEmptyElement)
                              {
                                  this.ReadRelations();
                              }
                          }
                          else
                          {
                              throw new Exception("Unknown child element <" + this.reader.Name + "> in parent element <" + Serialization.Population + ">");
                          }
  
                          break;
                      case XmlNodeType.EndElement:
                          if (!this.reader.Name.Equals(Serialization.Population))
                          {
                              throw new Exception("Expected closing element </" + Serialization.Population + ">");
                          }
  
                          return;
                  }
              }
          }
  
          private void ReadObjects()
          {
              while (this.reader.Read())
              {
                  switch (this.reader.NodeType)
                  {
                      case XmlNodeType.Element:
                          if (this.reader.Name.Equals(Serialization.Database))
                          {
                              if (!this.reader.IsEmptyElement)
                              {
                                  this.ReadObjectTypes();
                              }
                          }
                          else if (reader.Name.Equals(Serialization.Workspace))
                          {
                              throw new Exception("Can not load workspace objects in a Database.");
                          }
                          else
                          {
                              throw new Exception("Unknown child element <" + this.reader.Name + "> in parent element <" + Serialization.Objects + ">");
                          }
  
                          break;
                      case XmlNodeType.EndElement:
                          if (!this.reader.Name.Equals(Serialization.Objects))
                          {
                              throw new Exception("Expected closing element </" + Serialization.Objects + ">");
                          }
  
                          return;
                  }
              }
          }
  
          private void ReadObjectTypes()
          {
              while (this.reader.Read())
              {
                  switch (this.reader.NodeType)
                  {
                      // only process elements, ignore others
                      case XmlNodeType.Element:
                          if (this.reader.Name.Equals(Serialization.ObjectType))
                          {
                              if (!this.reader.IsEmptyElement)
                              {
                                  var objectTypeIdString = this.reader.GetAttribute(Serialization.Id);
                                  if (string.IsNullOrEmpty(objectTypeIdString))
                                  {
                                      throw new Exception("Object type id is missing");
                                  }
  
  
gt:                                 var objectTypeId = new Guid(objectTypeIdString);