/// <summary> /// Creates a proxy for the global table data cache. /// </summary> /// <param name="table"> The table metadata. </param> /// <returns> The proxy for the cache. </returns> private CachingTableDataLoader CreateCachedData(TableDescription table) { if (this.wrappedTableDataLoaderFactory == null) { this.wrappedTableDataLoaderFactory = this.wrappedDataLoader.CreateTableDataLoaderFactory(); } ITableDataLoader wrappedTableDataLoader = this.wrappedTableDataLoaderFactory.CreateTableDataLoader(table); return(new CachingTableDataLoader(wrappedTableDataLoader)); }
/// <summary> /// Loads the table data from the specified table data loader and materializes it /// bases on the specified metadata. /// </summary> /// <param name="loaderFactory"> The loader factory. </param> /// <param name="table"> The table metadata. </param> /// <returns> The materialized data. </returns> public static IEnumerable<object> Load( ITableDataLoaderFactory loaderFactory, DbTableInfo table) { List<ColumnDescription> columns = new List<ColumnDescription>(); PropertyInfo[] properties = table.EntityType.GetProperties(); Func<object, object>[] converters = new Func<object,object>[properties.Length]; for (int i = 0; i < properties.Length; i++) { PropertyInfo property = properties[i]; Type type = property.PropertyType; // TODO: external if (type == typeof(NMemory.Data.Timestamp)) { converters[i] = ConvertTimestamp; type = typeof(byte[]); } else if (type == typeof(NMemory.Data.Binary)) { converters[i] = ConvertBinary; type = typeof(byte[]); } ColumnDescription column = new ColumnDescription(property.Name, type); columns.Add(column); } TableDescription tableDescription = new TableDescription(table.TableName, columns); ITableDataLoader loader = loaderFactory.CreateTableDataLoader(tableDescription); // Prefetch require info/object to increase performance Func<object[], object> initializer = table.EntityInitializer; int columnCount = columns.Count; // Single array to spare GC object[] entityProperties = null; foreach (object[] data in loader.GetData()) { if (entityProperties == null) { // Initialize at the first element entityProperties = new object[data.Length]; } for (int i = 0; i < columnCount; i++) { object propertyValue = data[i]; // Use converter if required Func<object, object> converter = converters[i]; if (converter != null) { propertyValue = converter.Invoke(propertyValue); } entityProperties[i] = propertyValue; } yield return initializer.Invoke(entityProperties); } }
/// <summary> /// Loads the table data from the specified table data loader and materializes it /// bases on the specified metadata. /// </summary> /// <param name="loaderFactory"> The loader factory. </param> /// <param name="table"> The table metadata. </param> /// <returns> The materialized data. </returns> public static IEnumerable <object> Load( ITableDataLoaderFactory loaderFactory, DbTableInfo table) { List <ColumnDescription> columns = new List <ColumnDescription>(); PropertyInfo[] properties = table.EntityType.GetProperties(); Func <object, object>[] converters = new Func <object, object> [properties.Length]; for (int i = 0; i < properties.Length; i++) { PropertyInfo property = properties[i]; Type type = property.PropertyType; // TODO: external if (type == typeof(NMemory.Data.Timestamp)) { converters[i] = ConvertTimestamp; type = typeof(byte[]); } else if (type == typeof(NMemory.Data.Binary)) { converters[i] = ConvertBinary; type = typeof(byte[]); } ColumnDescription column = new ColumnDescription(property.Name, type); columns.Add(column); } TableDescription tableDescription = new TableDescription(table.TableName, columns); ITableDataLoader loader = loaderFactory.CreateTableDataLoader(tableDescription); // Prefetch require info/object to increase performance Func <object[], object> initializer = table.EntityInitializer; int columnCount = columns.Count; // Single array to spare GC object[] entityProperties = null; foreach (object[] data in loader.GetData()) { if (entityProperties == null) { // Initialize at the first element entityProperties = new object[data.Length]; } for (int i = 0; i < columnCount; i++) { object propertyValue = data[i]; // Use converter if required Func <object, object> converter = converters[i]; if (converter != null) { propertyValue = converter.Invoke(propertyValue); } entityProperties[i] = propertyValue; } yield return(initializer.Invoke(entityProperties)); } }
public void Initialize(DbSchema schema) { // TODO: locking Stopwatch fullTime = Stopwatch.StartNew(); Stopwatch partialTime = Stopwatch.StartNew(); this.Logger.Write("Database creation started..."); this.EnsureInitializedDatabase(); // Temporary dictionary Dictionary <string, ITable> tables = new Dictionary <string, ITable>(); this.Logger.Write("Creating tables..."); partialTime.Restart(); foreach (DbTableInfo tableInfo in schema.Tables) { ITable table = DatabaseReflectionHelper.CreateTable( this.Internal, tableInfo.EntityType, (IKeyInfo)tableInfo.PrimaryKeyInfo, tableInfo.IdentityField, tableInfo.ConstraintFactories); tables.Add(tableInfo.TableName, table); } this.Logger.Write( "Tables created in {0:0.0} ms", partialTime.Elapsed.TotalMilliseconds); this.Logger.Write("Adding initial data..."); partialTime.Restart(); // Add initial data to the tables using (ITableDataLoaderFactory loaderFactory = this.CreateDataLoaderFactory()) { foreach (DbTableInfo tableInfo in schema.Tables) { // Get the table reference from the temporary dictionary ITable table = tables[tableInfo.TableName]; // Return initial entity data and materialize them IEnumerable <object> data = ObjectLoader.Load(loaderFactory, tableInfo); DatabaseReflectionHelper.InitializeTableData(table, data); } } this.Logger.Write( "Initial data added in {0:0.0} ms", partialTime.Elapsed.TotalMilliseconds); this.Logger.Write("Building additional indexes..."); partialTime.Restart(); foreach (DbTableInfo tableInfo in schema.Tables) { ITable table = tables[tableInfo.TableName]; foreach (IKeyInfo key in tableInfo.UniqueKeys) { DatabaseReflectionHelper.CreateIndex(table, key, true); } foreach (IKeyInfo key in tableInfo.ForeignKeys) { DatabaseReflectionHelper.CreateIndex(table, key, false); } } this.Logger.Write( "Additional indexes built in {0:0.0} ms", partialTime.Elapsed.TotalMilliseconds); this.Logger.Write("Creating and verifying associations..."); partialTime.Restart(); foreach (DbRelationInfo relation in schema.Relations) { DatabaseReflectionHelper.CreateAssociation(this.Internal, relation); } this.Logger.Write( "Associations created and verfied in {0:0.0} ms", partialTime.Elapsed.TotalMilliseconds); this.Logger.Write( "Database creation finished in {0:0.0} ms", fullTime.Elapsed.TotalMilliseconds); }
/// <summary> /// Creates a proxy for the global table data cache. /// </summary> /// <param name="table"> The table metadata. </param> /// <returns> The proxy for the cache. </returns> private CachingTableDataLoader CreateCachedData(TableDescription table) { if (this.wrappedTableDataLoaderFactory == null) { this.wrappedTableDataLoaderFactory = this.wrappedDataLoader.CreateTableDataLoaderFactory(); } ITableDataLoader wrappedTableDataLoader = this.wrappedTableDataLoaderFactory.CreateTableDataLoader(table); return new CachingTableDataLoader(wrappedTableDataLoader); }