Лазерное хранилище таблиц, служба 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);