diff --git a/CoreHelpers.WindowsAzure.Storage.Table.Tests/ITS030SharedTable.cs b/CoreHelpers.WindowsAzure.Storage.Table.Tests/ITS030SharedTable.cs deleted file mode 100644 index e360e85..0000000 --- a/CoreHelpers.WindowsAzure.Storage.Table.Tests/ITS030SharedTable.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System; -using CoreHelpers.WindowsAzure.Storage.Table.Tests.Extensions; -using CoreHelpers.WindowsAzure.Storage.Table.Tests.Models; -using Xunit.DependencyInjection; - -namespace CoreHelpers.WindowsAzure.Storage.Table.Tests -{ - [Startup(typeof(Startup))] - [Collection("Sequential")] - public class ITS030SharedTable - { - private readonly IStorageContext _rootContext; - - public ITS030SharedTable(IStorageContext context) - { - _rootContext = context; - - } - - - [Fact] - public async Task VerifyGetItem() - { - using (var scp = _rootContext.CreateChildContext()) - { - // set the tablename context - scp.SetTableContext(); - - // configure the entity mapper - scp.AddAttributeMapper(typeof(MultipleModelsBase)); - - - var model1 = new MultipleModels1() { P = "P1", Contact = "C1", Model1Field = "Model1Field" }; - var model2 = new MultipleModels2() { P = "P1", Contact = "C2", Model2Field = "Model2Field" }; - - - scp.EnableAutoCreateTable(); - - await scp.MergeOrInsertAsync(new[] {model1}); - await scp.MergeOrInsertAsync(new[] {model2}); - - - var result1 = await scp.QueryAsync("P1", "C1"); - Assert.Equivalent(model1, result1, true); - Assert.IsType(result1); - - var result2 = await scp.QueryAsync("P1", "C2"); - Assert.Equivalent(model2, result2, true); - Assert.IsType(result2); - - // cleanup - await scp.DropTableAsync(); - } - } - - } -} diff --git a/CoreHelpers.WindowsAzure.Storage.Table.Tests/Models/MultipleModels.cs b/CoreHelpers.WindowsAzure.Storage.Table.Tests/Models/MultipleModels.cs deleted file mode 100644 index 07fd04e..0000000 --- a/CoreHelpers.WindowsAzure.Storage.Table.Tests/Models/MultipleModels.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using System.Collections.Generic; -using CoreHelpers.WindowsAzure.Storage.Table.Attributes; - -namespace CoreHelpers.WindowsAzure.Storage.Table.Tests.Models -{ - - [Storable(TypeField = nameof(Type))] - public class MultipleModelsBase - { - [PartitionKey] - public string P { get; set; } = "Partition01"; - - [RowKey] - public string Contact { get; set; } = String.Empty; - - } - - public class MultipleModels1 : MultipleModelsBase - { - public string Model1Field { get; set; } = String.Empty; - - } - - public class MultipleModels2 : MultipleModelsBase - { - public string Model2Field { get; set; } = String.Empty; - - } - -} diff --git a/CoreHelpers.WindowsAzure.Storage.Table/Attributes/StorableAttribute.cs b/CoreHelpers.WindowsAzure.Storage.Table/Attributes/StorableAttribute.cs index 36ba837..41dd5f4 100644 --- a/CoreHelpers.WindowsAzure.Storage.Table/Attributes/StorableAttribute.cs +++ b/CoreHelpers.WindowsAzure.Storage.Table/Attributes/StorableAttribute.cs @@ -6,17 +6,9 @@ namespace CoreHelpers.WindowsAzure.Storage.Table.Attributes public class StorableAttribute : Attribute { public string Tablename { get; set; } - - public string TypeField { get; set; } = null; public StorableAttribute() {} - public StorableAttribute(string Tablename, string TypeField) - { - this.Tablename = Tablename; - this.TypeField = TypeField; - } - public StorableAttribute(string Tablename) { this.Tablename = Tablename; diff --git a/CoreHelpers.WindowsAzure.Storage.Table/Internal/StorageContextQueryNow.cs b/CoreHelpers.WindowsAzure.Storage.Table/Internal/StorageContextQueryNow.cs index 357a7ca..127e257 100644 --- a/CoreHelpers.WindowsAzure.Storage.Table/Internal/StorageContextQueryNow.cs +++ b/CoreHelpers.WindowsAzure.Storage.Table/Internal/StorageContextQueryNow.cs @@ -3,7 +3,6 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; -using System.Reflection; using System.Runtime.ExceptionServices; using System.Threading; using System.Threading.Tasks; @@ -95,20 +94,8 @@ private bool MoveNextInternal(bool initialPage) return MoveNextInternal(false); } - var entityMapper = _context.context.GetEntityMapper(); - // set the item - if (entityMapper.TypeField == null) - Current = TableEntityDynamic.fromEntity(_inPageEnumerator.Current, entityMapper); - else - { - var entity = _inPageEnumerator.Current; - var typeName = entity.GetString(entityMapper.TypeField); - Type type = Type.GetType(typeName); - MethodInfo method = typeof(TableEntityDynamic).GetMethod(nameof(TableEntityDynamic.fromEntity)); - MethodInfo genericMethod = method.MakeGenericMethod(type); - Current = genericMethod.Invoke(null, [_inPageEnumerator.Current, entityMapper] ) as T; - } + Current = TableEntityDynamic.fromEntity(_inPageEnumerator.Current, _context.context.GetEntityMapper()); // done return true; diff --git a/CoreHelpers.WindowsAzure.Storage.Table/Serialization/TableEntityDynamic.cs b/CoreHelpers.WindowsAzure.Storage.Table/Serialization/TableEntityDynamic.cs index 9dc4f50..68b5515 100644 --- a/CoreHelpers.WindowsAzure.Storage.Table/Serialization/TableEntityDynamic.cs +++ b/CoreHelpers.WindowsAzure.Storage.Table/Serialization/TableEntityDynamic.cs @@ -29,20 +29,12 @@ internal static class TableEntityDynamic builder.AddPartitionKey(GetTableStorageDefaultProperty(entityMapper.PartitionKeyFormat, model)); builder.AddRowKey(GetTableStorageDefaultProperty(entityMapper.RowKeyFormat, model), entityMapper.RowKeyEncoding); - var modelType = model.GetType(); - // get all properties from model - IEnumerable objectProperties = modelType.GetTypeInfo().GetProperties(); - - // it is not required and preferred NOT to have the type field in the model as we can ensure equality - builder.AddProperty(entityMapper.TypeField, modelType.AssemblyQualifiedName); + IEnumerable objectProperties = model.GetType().GetTypeInfo().GetProperties(); // visit all properties foreach (PropertyInfo property in objectProperties) { - if (property.Name == entityMapper.TypeField) - continue; - if (ShouldSkipProperty(property)) continue; diff --git a/CoreHelpers.WindowsAzure.Storage.Table/StoargeEntityMapper.cs b/CoreHelpers.WindowsAzure.Storage.Table/StoargeEntityMapper.cs index e3803de..4003157 100644 --- a/CoreHelpers.WindowsAzure.Storage.Table/StoargeEntityMapper.cs +++ b/CoreHelpers.WindowsAzure.Storage.Table/StoargeEntityMapper.cs @@ -9,7 +9,6 @@ public class StorageEntityMapper public String RowKeyFormat { get; set; } public nVirtualValueEncoding RowKeyEncoding { get; set; } public String TableName { get; set; } - public string TypeField { get; internal set; } public StorageEntityMapper() {} diff --git a/CoreHelpers.WindowsAzure.Storage.Table/StorageContextAttributeMapping.cs b/CoreHelpers.WindowsAzure.Storage.Table/StorageContextAttributeMapping.cs index 8ef27ac..995d5fb 100644 --- a/CoreHelpers.WindowsAzure.Storage.Table/StorageContextAttributeMapping.cs +++ b/CoreHelpers.WindowsAzure.Storage.Table/StorageContextAttributeMapping.cs @@ -62,18 +62,12 @@ public void AddAttributeMapper(Type type) public void AddAttributeMapper(Type type, String optionalTablenameOverride) { - string typeField = null; - // get the concrete attribute var storableAttribute = type.GetTypeInfo().GetCustomAttribute(); if (String.IsNullOrEmpty(storableAttribute.Tablename)) { storableAttribute.Tablename = type.Name; } - if (!String.IsNullOrEmpty(storableAttribute.TypeField)) - { - typeField = storableAttribute.TypeField; - } // store the neded properties string partitionKeyFormat = null; @@ -117,8 +111,7 @@ public void AddAttributeMapper(Type type, String optionalTablenameOverride) TableName = String.IsNullOrEmpty(optionalTablenameOverride) ? storableAttribute.Tablename : optionalTablenameOverride, PartitionKeyFormat = partitionKeyFormat, RowKeyFormat = rowKeyFormat, - RowKeyEncoding = rowKeyEncoding, - TypeField = typeField, + RowKeyEncoding = rowKeyEncoding }); } diff --git a/README.md b/README.md index 2e43bf9..99ebc39 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,5 @@ [![Build Status](https://github.com/CoreHelpers/AzureStorageTable/actions/workflows/ci-build.yml/badge.svg)](https://github.com/CoreHelpers/AzureStorageTable/actions/workflows/ci-build.yml) -! NOTICE THIS IS A CUSTOM BUILD OF AzureStorageTable that contains the following additional features: -* Multiple Types in the same table (Base objects) - # AzureStorageTable This projects implements an abstraction for Azure Storage Tables to use POCOs because deriving every entity from ITableEntity or TableEntity looks like a step backwards. The current implementation is intended to be an @@ -162,56 +159,6 @@ public class JObjectModel } ``` -## Store Multiple Objects Types in the same Table -If multiple objects share a common base class, it can be used to store them in the same table. The base class must be decorated with the Storable attribute with the `TypeField` parameter set. It is best practice to NOT include the type field in the model. - -```csharp - [Storable(TypeField = "Type")] - public class BaseModel - { - [PartitionKey] - public string P { get; set; } = "Partition01"; - - [RowKey] - public string R { get; set; } = String.Empty; - - } - - public class MultipleModels1 : MultipleModelsBase - { - public string Model1Field { get; set; } = String.Empty; - - } - - public class MultipleModels2 : MultipleModelsBase - { - public string Model2Field { get; set; } = String.Empty; - - } - -``` - -When saving and querying it is important to use the base class as the generic type. - -```csharp - using (var storageContext = new StorageContext(storageKey, storageSecret)) - { - storageContext.AddAttributeMapper(); - - storageContext.CreateTable(); - - storageContext.MergeOrInsert(new MultipleModels1() { R = "Row01", Model1Field = "Model1Field" }); - storageContext.MergeOrInsert(new MultipleModels2() { R = "Row02", Model2Field = "Model2Field" }); - - var result = storageContext.Query(); - - foreach (var r in result) - { - Console.WriteLine(r.GetType().Name); - } - } -``` - # Contributing to Azure Storage Table Fork as usual and go crazy!