Лазерное хранилище таблиц, служба WCF и перечисление
Вот моя проблема. Класс, который определяет порядок, имеет свойство PaymentStatus
, которое является enum
, определенным так:
public enum PaymentStatuses : int
{
OnDelivery = 1,
Paid = 2,
Processed = 3,
Cleared = 4
}
И позже, в самом классе, определение свойства очень просто:
public PaymentStatuses? PaymentStatus { get; set; }
Однако, если я попытаюсь сохранить заказ в хранилище таблиц Azure, я получаю следующее исключение:
System.InvalidOperationException: The type Order+PaymentStatuses' has no settable properties.
В этот момент я думал, что использование enum
невозможно, но быстрый поиск в Google возвратил это: http://social.msdn.microsoft.com/Forums/en-US/windowsazure/thread/7eb1a2ca-6c1b-4440-b40e-012db98ccb0a
На этой странице перечислены два ответа, один из которых, кажется, игнорирует проблемы и предполагает, что использование enum
в Azure Storage в порядке.
Теперь мне не нужно хранить enum
в хранилище таблиц Azure как таковое, я мог бы также сохранить соответствующий int
, однако мне нужно, чтобы это свойство отображалось в службе WCF.
Я попытался использовать свойство get
и set
для возврата enum
из сохраненного integer
и удалить это свойство из Azure с помощью события WritingEntity
на моем DataContext
, но я получаю это исключение до того, как событие для этого объекта запущено.
В этот момент я в недоумении, я не знаю, что еще я могу сделать, чтобы это свойство в WCF было enum
, но у Azure есть только int
.
Ответы
Ответ 1
Enum не поддерживается. Несмотря на то, что он определен как int, он действительно не является интегральным типом, поддерживаемым Storage Table. Ниже приведен список поддерживаемых типов. Перечисление - это просто строковое выражение целочисленного числа с объектно-ориентированным ароматом.
Вы можете хранить int в хранилище таблиц, а затем скрывать его с помощью Enum.Parse.
Ответ 2
Вот простой способ:
public int MyEnumValue { get; set; } //for use by the Azure client libraries only
[IgnoreProperty] public MyEnum MyEnum
{
get { return (MyEnum) MyEnumValue; }
set { MyEnumValue = (int) value; }
}
Было бы лучше, если бы простая базовая ценность могла быть использована, а не дополнительное (общедоступное) свойство - без хлопот переопределения ReadEntity
/WriteEntity
, конечно. Я открыл голосовое голосовое сообщение , которое облегчило бы это, чтобы вы могли его увеличить.
Ответ 3
У меня была эта же проблема
Я изменил свое свойство, которое было ранее enum для int. теперь это свойство int анализирует входящий int и сохраняет его в variale того же типа перечисления, поэтому теперь код, который был
public CompilerOutputTypes Type
{get; set;}
передается
private CompilerOutputTypes type;
public int Type
{
get {return (int)type;}
set { type = (CompilerOutputTypes)value; }
}
Ответ 4
Только предложения...
Я помню, что в WCF вы должны отмечать перечисления со специальными атрибутами: http://msdn.microsoft.com/en-us/library/aa347875.aspx
Кроме того, когда вы объявляете PaymentStatuses? PaymentStatus
, вы объявляете Nullable<PaymentStatuses> PaymentStatus
. Синтакс ?
- это просто синтаксический сахар. Попробуйте удалить ?
и посмотреть, что произойдет (вы можете добавить PaymentStatuses.NoSet = 0, потому что значение по умолчанию для Int32 равно 0).
Удачи.
Ответ 5
Решение Parvs поставило меня на правильный путь, но у меня были небольшие корректировки.
private string _EnumType;
private EnumType _Type;
//*********************************************
//*********************************************
public string EnumType
{
get { return _Type.ToString(); }
set
{
_EnumType = value;
try
{
_Type = (EnumType)Enum.Parse(typeof(EnumType), value);
}
catch (Exception)
{
_EnumType = "Undefined";
_Type = [mynamespace].EnumType.Undefined;
}
}
}
Ответ 6
Я столкнулся с подобной проблемой и реализовал общий API-интерфейс flattener/recomposer для объектов, который сгладит ваши сложные объекты в плоские словари EntityProperty
и сделает их доступными для хранения таблиц в форме DynamicTableEntity
.
Затем тот же API перекомпонует весь сложный объект из словаря EntityProperty
DynamicTableEntity
.
Это относится к вашему вопросу, потому что API ObjectFlattenerRecomposer поддерживает выравнивание типов свойств, которые обычно не записываются в хранилище таблиц Azure, например Enum
, TimeSpan
, все Nullable
, ulong
и uint
путем преобразования их можно записывать EntityProperties.
API также обрабатывает преобразование обратно к исходному сложному объекту из сплющенного словаря EntityProperty
. Все, что нужно сделать клиенту, это сказать API, у меня есть этот словарь EntityProperty
, который я только что прочитал из таблицы Azure (в виде DynamicTableEntity.Properties), можете ли вы преобразовать его в объект этого конкретного типа. API будет перекомпоновать полный комплексный объект со всеми его свойствами, включая свойства "Enum" с их исходными правильными значениями.
Все это сглаживание и перекомпоновка исходного объекта осуществляется прозрачно клиенту (пользователю API). Клиенту не нужно предоставлять какую-либо схему или любое знание API ObjectFlattenerRecomposer о сложном объекте, который он хочет написать, он просто передает объект API как "объект", чтобы сгладить его. При преобразовании обратно клиент должен только предоставить фактический тип объекта, к которому хочет преобразовать сплющенный EntityProperty
словарь. Общий метод ConvertBack API просто рекомпозирует исходный объект Type T и возвращает его клиенту.
См. пример использования ниже. Объектам не нужно реализовывать какой-либо интерфейс, например, "ITableEntity" или наследовать от определенного базового класса. Им не нужно предоставлять специальный набор конструкторов.
Блог: https://doguarslan.wordpress.com/2016/02/03/writing-complex-objects-to-azure-table-storage/
Пакет Nuget: https://www.nuget.org/packages/ObjectFlattenerRecomposer/
Применение:
//Flatten object (ie. of type Order) and convert it to EntityProperty Dictionary
Dictionary<string, EntityProperty> flattenedProperties = EntityPropertyConverter.Flatten(order);
// Create a DynamicTableEntity and set its PK and RK
DynamicTableEntity dynamicTableEntity = new DynamicTableEntity(partitionKey, rowKey);
dynamicTableEntity.Properties = flattenedProperties;
// Write the DynamicTableEntity to Azure Table Storage using client SDK
//Read the entity back from AzureTableStorage as DynamicTableEntity using the same PK and RK
DynamicTableEntity entity = [Read from Azure using the PK and RK];
//Convert the DynamicTableEntity back to original complex object.
Order order = EntityPropertyConverter.ConvertBack<Order>(entity.Properties);