public void CachingDataLoaderFactory_InvokesLatch() { var latchMock = new DataLoaderConfigurationLatchMock(); var dataLoaderStub = new FakeDataLoader(); var table = new TableDescription("table", Enumerable.Empty<ColumnDescription>()); var storeProxy = CreateFakeStoreProxy(); ITableDataLoaderFactory factory = new CachingTableDataLoaderFactory(dataLoaderStub, latchMock, storeProxy); // The latch should not have been invoked yet Assert.AreEqual(0, latchMock.AcquireCallCount); Assert.AreEqual(0, latchMock.ReleaseCallCount); using (factory) { // This invocation should make the factory using the latch factory.CreateTableDataLoader(table); // The latch should have been acquired Assert.AreEqual(1, latchMock.AcquireCallCount); Assert.AreEqual(0, latchMock.ReleaseCallCount); } // The latch should have been released Assert.AreEqual(1, latchMock.AcquireCallCount); Assert.AreEqual(1, latchMock.ReleaseCallCount); }
/// <summary> /// Initializes a new instance of the <see cref="CsvTableDataLoader" /> class. /// </summary> /// <param name="file"> The file reference to the CSV file. </param> /// <param name="table"> The metadata of the requested table. </param> public CsvTableDataLoader(IFileReference file, TableDescription table) : base(table) { // TODO: Constructor injection this.valueConverter = new CsvValueConverter(); this.file = file; }
/// <summary> /// Initializes a new instance of the <see cref="EntityTableDataLoader" /> class. /// </summary> /// <param name="connection"> The connection towards the database. </param> /// <param name="table"> The metadata of the table. </param> public EntityTableDataLoader(EntityConnection connection, TableDescription table) : base(table) { this.connection = connection; this.workspace = connection.GetMetadataWorkspace(); this.entitySet = MetadataWorkspaceHelper .GetEntityContainer(this.workspace) .GetEntitySetByName(table.Name, true); }
/// <summary> /// Ensures that a connection is established towards to appropriate database and /// creates a <see cref="EntityTableDataLoader" /> instance for the specified /// table. /// </summary> /// <param name="table"> /// The metadata of the table. /// </param> /// <returns> /// The <see cref="EntityTableDataLoader" /> instance for the table. /// </returns> public ITableDataLoader CreateTableDataLoader(TableDescription table) { if (this.connection == null) { this.connection = this.connectionFactory.Invoke(); this.connection.Open(); } return new EntityTableDataLoader(this.connection, table); }
/// <summary> /// Creates a data loader for the specified table. /// </summary> /// <param name="table">The metadata of the table.</param> /// <returns> /// The data loader for the table. /// </returns> public ITableDataLoader CreateTableDataLoader(TableDescription table) { if (!data.HasTable(table.Name)) return new EmptyTableDataLoader(); var entityType = data.TableType(table.Name); var type = LoaderType.MakeGenericType(entityType); var constructor = type.GetConstructor(new[] { typeof (TableDescription), typeof (IEnumerable<>).MakeGenericType(entityType) }); return (ITableDataLoader)constructor.Invoke(new[] { table, data.GetTable(table.Name) }); }
/// <summary> /// Creates a <see cref="CsvTableDataLoader" /> instance for the specified table. /// </summary> /// <param name="table"> /// The metadata of the table. /// </param> /// <returns> /// The <see cref="CsvTableDataLoader" /> instance for the table. /// </returns> public ITableDataLoader CreateTableDataLoader(TableDescription table) { string name = string.Format("{0}.csv", table.Name); IFileReference file = this.source.GetFile(name); if (file == null || !file.Exists) { return new EmptyTableDataLoader(); } return new CsvTableDataLoader(file, table); }
public ITableDataLoader CreateTableDataLoader(TableDescription tableDescription) { if (tableDescription == null) throw new ArgumentNullException("tableDescription"); if (!_bindings.ContainsKey(tableDescription.Name)) return new EmptyTableDataLoader(); var entry = _bindings.Single(x => x.Key == tableDescription.Name); return new EntityObjectDataLoaderWrapper( (IEntityDataLoader<object>)Activator.CreateInstance(Type.GetType(entry.Value, throwOnError: false)), tableDescription.Columns ); }
public void CachingDataLoaderFactory_IgnoresLatch() { var latchMock = new DataLoaderConfigurationLatchMock(); var stub = new FakeDataLoader(); var storeProxy = CreateFakeStoreProxy(); var table = new TableDescription("table", Enumerable.Empty<ColumnDescription>()); ITableDataLoaderFactory factory = new CachingTableDataLoaderFactory(stub, latchMock, storeProxy); using (factory) { // The CreateTableDataLoader is not invoked } // The latch should not have been invoked Assert.AreEqual(0, latchMock.AcquireCallCount); }
public void CachingDataLoaderFactory_SingleTablesSingleQuery() { var dataLoaderMock = new FakeDataLoader(); var storeProxy = CreateFakeStoreProxy(); ITableDataLoaderFactory factory = new CachingTableDataLoaderFactory(dataLoaderMock, null, storeProxy); // First call var table = new TableDescription("table", Enumerable.Empty<ColumnDescription>()); factory.CreateTableDataLoader(table); // Second call (should return the ITableDataLoader from cache) factory.CreateTableDataLoader(table); Assert.AreEqual(1, dataLoaderMock.CreateTableDataLoaderCallCount); Assert.AreEqual(1, storeProxy.CachedItemReturnCount); }
public void CachingDataLoaderFactory_MoreTablesMoreQuery() { var dataLoaderMock = new FakeDataLoader(); var storeProxy = CreateFakeStoreProxy(); ITableDataLoaderFactory factory = new CachingTableDataLoaderFactory(dataLoaderMock, null, storeProxy); // First call var table1 = new TableDescription("table1", Enumerable.Empty<ColumnDescription>()); factory.CreateTableDataLoader(table1); // Second call (another table, the cache should not be used) var table2 = new TableDescription("table2", Enumerable.Empty<ColumnDescription>()); factory.CreateTableDataLoader(table2); Assert.AreEqual(2, dataLoaderMock.CreateTableDataLoaderCallCount); Assert.AreEqual(0, storeProxy.CachedItemReturnCount); }
public void CachingDataLoaderFactory_ReturnsSameData() { var latchMock = new DataLoaderConfigurationLatchMock(); var stub = new FakeDataLoader(); var storeProxy = CreateFakeStoreProxy(); var table = new TableDescription("table", Enumerable.Empty<ColumnDescription>()); CachingTableDataLoaderFactory factory = new CachingTableDataLoaderFactory(stub, latchMock, storeProxy); var data1 = factory.CreateTableDataLoader(table).GetData(); var data2 = factory.CreateTableDataLoader(table).GetData(); Enumerable.SequenceEqual(data1, data2); // The returned datasets should be exactly the same (same reference) Assert.AreEqual(data1, data2); }
/// <summary> /// Initializes a new instance of the <see cref="TableDataLoaderBase" /> class. /// </summary> /// <param name="table"> The metadata of the table. </param> public TableDataLoaderBase(TableDescription table) { this.table = table; }
/// <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.Schema, table.TableName.Name, 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 ITableDataLoader CreateTableDataLoader(TableDescription table) { this.CreateTableDataLoaderCallCount++; return new FakeTableDataLoader(); }
/// <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> /// Creates a data loader for the specified table. /// </summary> /// <param name="table"> The metadata of the table. </param> /// <returns> /// The data loader for the table. /// </returns> public ITableDataLoader CreateTableDataLoader(TableDescription table) { CachingTableDataLoaderKey key = new CachingTableDataLoaderKey( new DataLoaderConfigurationKey(this.wrappedDataLoader), table.Name); // If the table data cache does not exists, then the data loader configuration // should be locked if (latch != null && !this.dataStore.Contains(key)) { // Wait for the lock, this could take some time latch.Acquire(); // Check if the data was created since the waiting if (this.dataStore.Contains(key)) { latch.Release(); } } // It does not matter if the table data cache was created during the waiting, // maybe there is still tables thats data is not fetched return this.dataStore.GetCachedData(key, () => CreateCachedData(table)); }
/// <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); }
public ITableDataLoader CreateTableDataLoader(TableDescription table) { return new EntityObjectDataLoaderWrapper(_bindings[table.Name], table.Columns); }