Хранилище таблиц Azure, служба WCF и Enum - PullRequest
11 голосов
/ 02 февраля 2011

Вот моя проблема.Класс, который определяет порядок, имеет свойство с именем 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.

Теперь мне НЕ НУЖНО хранить enum в хранилище таблиц Azure как таковом, я также мог бы хранить соответствующее int, однако мне нужно, чтобы это свойство было открыто в службе WCF..

Я пытался заставить свойство использовать get и set, чтобы вернуть enum из сохраненного integer и удалить это свойство из Azure, используя событие WritingEntity на моемDataContext, но я получаю это исключение перед событием дляэта сущность запущена.

На данный момент, я в растерянности, я не знаю, что еще я могу сделать, чтобы это свойство в WCF было enum, но хранилище Azure толькоint.

Ответы [ 6 ]

16 голосов
/ 05 мая 2011

Enum не поддерживается. Хотя он определен как int, он на самом деле не является целочисленным типом, поддерживаемым Table Storage. Вот список поддерживаемых типов. Перечисление - это просто строковое выражение целого числа с объектно-ориентированной разновидностью.

Вы можете сохранить int в табличном хранилище, а затем скрыть его с помощью Enum.Parse.

12 голосов
/ 05 января 2015

Вот простой обходной путь:

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 голосов
/ 14 июля 2011

у меня возникла такая же проблема, я изменил свой объект, который был ранее enum на int.теперь это свойство int анализирует входящее int и сохраняет его в переменную с тем же типом enum, поэтому теперь код, который был

public CompilerOutputTypes Type 
{get; set;}

, преобразован в

private CompilerOutputTypes type;
public int Type 
{
  get {return (int)type;}
  set { type = (CompilerOutputTypes)value; }
}
0 голосов
/ 11 марта 2016

Я столкнулся с подобной проблемой и реализовал универсальный API выравнивания / перекомпоновки объектов, который сведет ваши сложные сущности в плоские словари EntityProperty и сделает их доступными для записи в Table Storage в виде 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 просто перекомпоновывает исходный объект типа 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);
0 голосов
/ 28 июня 2013

Решение 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;                  
            }                        
        }
    }
0 голосов
/ 04 февраля 2011

Просто предложения ...

Я помню, что в WCF вы должны отмечать перечисления специальными атрибутами: http://msdn.microsoft.com/en-us/library/aa347875.aspx

Кроме того, когда вы объявляете PaymentStatuses? PaymentStatus, вы объявляете Nullable<PaymentStatuses> PaymentStatus. Синтаксис ? - это просто синтаксический сахар. Попробуйте удалить ? и посмотрите, что произойдет (вы можете добавить PaymentStatuses.NoSet = 0, поскольку значение по умолчанию для Int32 равно 0).

Удачи.

...