diff --git a/CoreHelpers.WindowsAzure.Storage.Table.Tests/ITS025StoreEnum.cs b/CoreHelpers.WindowsAzure.Storage.Table.Tests/ITS025StoreEnum.cs new file mode 100644 index 0000000..f11b792 --- /dev/null +++ b/CoreHelpers.WindowsAzure.Storage.Table.Tests/ITS025StoreEnum.cs @@ -0,0 +1,59 @@ +using System; +using CoreHelpers.WindowsAzure.Storage.Table.Tests.Contracts; +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 ITS025StoreEnum + { + private readonly IStorageContext _rootContext; + + public ITS025StoreEnum(IStorageContext context) + { + _rootContext = context; + } + + [Fact] + public async Task VerifyAttributeMapper() + { + using (var storageContext = _rootContext.CreateChildContext()) + { + // set the tablename context + storageContext.SetTableContext(); + + // create a new user + var user = new UserModel4() { FirstName = "Egon", LastName = "Mueller", Contact = "em@acme.org", UserType = UserTypeEnum.Pro }; + + // ensure we are using the attributes + storageContext.AddAttributeMapper(); + + // ensure the table exists + await storageContext.CreateTableAsync(); + + // inser the model + await storageContext.MergeOrInsertAsync(user); + + // query all + var result = await storageContext.QueryAsync(); + Assert.Single(result); + Assert.Equal("Egon", result.First().FirstName); + Assert.Equal("Mueller", result.First().LastName); + Assert.Equal("em@acme.org", result.First().Contact); + Assert.Equal(UserTypeEnum.Pro, result.First().UserType); + + // Clean up + await storageContext.DeleteAsync(result); + result = await storageContext.QueryAsync(); + Assert.NotNull(result); + Assert.Empty(result); + + await storageContext.DropTableAsync(); + } + } + } +} + diff --git a/CoreHelpers.WindowsAzure.Storage.Table.Tests/Models/UserModel4.cs b/CoreHelpers.WindowsAzure.Storage.Table.Tests/Models/UserModel4.cs new file mode 100644 index 0000000..05f4cc5 --- /dev/null +++ b/CoreHelpers.WindowsAzure.Storage.Table.Tests/Models/UserModel4.cs @@ -0,0 +1,28 @@ +using System; +using CoreHelpers.WindowsAzure.Storage.Table.Attributes; + +namespace CoreHelpers.WindowsAzure.Storage.Table.Tests.Models +{ + + public enum UserTypeEnum + { + Free, + Pro + } + + [Storable()] + public class UserModel4 + { + [PartitionKey] + public string P { get; set; } = "Partition01"; + + [RowKey] + public string Contact { get; set; } = String.Empty; + + public string FirstName { get; set; } = String.Empty; + public string LastName { get; set; } = String.Empty; + + public UserTypeEnum UserType { get; set; } + + } +} diff --git a/CoreHelpers.WindowsAzure.Storage.Table/Internal/StorageContextQueryNow.cs b/CoreHelpers.WindowsAzure.Storage.Table/Internal/StorageContextQueryNow.cs index e556dc0..127e257 100644 --- a/CoreHelpers.WindowsAzure.Storage.Table/Internal/StorageContextQueryNow.cs +++ b/CoreHelpers.WindowsAzure.Storage.Table/Internal/StorageContextQueryNow.cs @@ -140,9 +140,11 @@ private void InitializePageEnumeratorIfNeeded() // evaluate the maxItems int? maxPerPage = _context.maxPerPage.HasValue && _context.maxPerPage.Value > 0 ? _context.maxPerPage : null; - + + // fix Azurite bug + var filter = string.IsNullOrWhiteSpace(_context.filter) ? null : _context.filter; // start the query - _pageEnumerator = tc.Query(_context.filter, maxPerPage, _context.select, _context.cancellationToken).AsPages().GetEnumerator(); + _pageEnumerator = tc.Query(filter, maxPerPage, _context.select, _context.cancellationToken).AsPages().GetEnumerator(); } } diff --git a/CoreHelpers.WindowsAzure.Storage.Table/Serialization/TableEntityDynamic.cs b/CoreHelpers.WindowsAzure.Storage.Table/Serialization/TableEntityDynamic.cs index 503dce5..68b5515 100644 --- a/CoreHelpers.WindowsAzure.Storage.Table/Serialization/TableEntityDynamic.cs +++ b/CoreHelpers.WindowsAzure.Storage.Table/Serialization/TableEntityDynamic.cs @@ -17,11 +17,11 @@ internal static class TableEntityDynamic { if (context as StorageContext == null) throw new Exception("Invalid interface implemnetation"); - else + else return TableEntityDynamic.ToEntity(model, (context as StorageContext).GetEntityMapper()); } - public static TableEntity ToEntity(T model, StorageEntityMapper entityMapper) where T: new() + public static TableEntity ToEntity(T model, StorageEntityMapper entityMapper) where T : new() { var builder = new TableEntityBuilder(); @@ -42,11 +42,13 @@ internal static class TableEntityDynamic // properties with the correct converter var virtualTypeAttribute = property.GetCustomAttributes().Where(a => a is IVirtualTypeAttribute).Select(a => a as IVirtualTypeAttribute).FirstOrDefault(); if (virtualTypeAttribute != null) - virtualTypeAttribute.WriteProperty(property, model, builder); + virtualTypeAttribute.WriteProperty(property, model, builder); + else if (property.PropertyType.IsEnum) + builder.AddProperty(property.Name, property.GetValue(model, null).ToString()); else - builder.AddProperty(property.Name, property.GetValue(model, null)); + builder.AddProperty(property.Name, property.GetValue(model, null)); } - + // build the result return builder.Build(); } @@ -58,13 +60,13 @@ internal static class TableEntityDynamic // get all properties from model IEnumerable objectProperties = model.GetType().GetTypeInfo().GetProperties(); - + // visit all properties foreach (PropertyInfo property in objectProperties) { if (ShouldSkipProperty(property)) continue; - + // check if we have a special convert attached via attribute if so generate the required target // properties with the correct converter var virtualTypeAttribute = property.GetCustomAttributes().Where(a => a is IVirtualTypeAttribute).Select(a => a as IVirtualTypeAttribute).FirstOrDefault(); @@ -80,8 +82,12 @@ internal static class TableEntityDynamic if (!entity.TryGetValue(property.Name, out objectValue)) continue; - if (property.PropertyType == typeof(DateTime) || property.PropertyType == typeof(DateTime?) || property.PropertyType == typeof(DateTimeOffset) || property.PropertyType == typeof(DateTimeOffset?) ) + if (property.PropertyType == typeof(DateTime) || property.PropertyType == typeof(DateTime?) || property.PropertyType == typeof(DateTimeOffset) || property.PropertyType == typeof(DateTimeOffset?)) property.SetDateTimeOffsetValue(model, objectValue); + else if (property.PropertyType.IsEnum && int.TryParse(objectValue.ToString(), out var intEnum) && property.PropertyType.IsEnumDefined(intEnum)) + property.SetValue(model, Enum.ToObject(property.PropertyType, intEnum)); + else if (property.PropertyType.IsEnum && property.PropertyType.IsEnumDefined(objectValue.ToString())) + property.SetValue(model, Enum.Parse(property.PropertyType, objectValue.ToString())); else property.SetValue(model, objectValue); }