【问题标题】:Azure Table Storage, WCF Service and EnumAzure 表存储、WCF 服务和枚举
【发布时间】:2011-06-20 02:17:16
【问题描述】:

这是我的问题。定义订单的类有一个名为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 是不可能的,但快速谷歌搜索返回:http://social.msdn.microsoft.com/Forums/en-US/windowsazure/thread/7eb1a2ca-6c1b-4440-b40e-012db98ccb0a

此页面列出了两个答案,其中一个似乎忽略了问题,并建议在 Azure 存储中使用 enum 即可。

现在,我不需要将 enum 存储在 Azure 表存储中,我也可以存储相应的 int,但是,我确实需要在 WCF 服务中公开此属性.

我尝试让属性使用getset 从存储的integer 中返回enum,并通过在我的DataContext 上使用WritingEntity 事件从Azure 中删除此属性,但是在触发该实体的事件之前,我得到了该异常。

此时,我不知所措,我不知道我还能做些什么才能在 WCF 中将此属性作为 enum,但让 Azure 仅存储 int

【问题讨论】:

    标签: visual-studio-2010 enums azure wcf azure-table-storage


    【解决方案1】:

    不支持枚举。尽管它被定义为一个 int 类型,但它实际上并不是 Table Storage 支持的整数类型。 Here is the list of types supported. 枚举只是整数的字符串表达式,具有面向对象的风格。

    您可以将 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 的麻烦。我打开了一个 user voice ticket 来促进这一点,所以你可能想要投票。

      【讨论】:

        【解决方案3】:

        是的,我遇到了同样的问题 我将之前枚举的属性更改为 int。现在这个 int 属性解析传入的 int 并将其保存到相同枚举类型的变量中,所以现在的代码是

        public CompilerOutputTypes Type 
        {get; set;}
        

        改成

        private CompilerOutputTypes type;
        public int Type 
        {
          get {return (int)type;}
          set { type = (CompilerOutputTypes)value; }
        }
        

        【讨论】:

        • 在我的情况下,这不是一个有效的解决方案:使用枚举的 WCF 服务仍然需要对整数而不是枚举进行操作。
        【解决方案4】:

        只是建议...

        我记得在 WCF 中你必须用特殊属性标记枚举:http://msdn.microsoft.com/en-us/library/aa347875.aspx

        此外,当您声明 PaymentStatuses? PaymentStatus 时,您就是在声明 Nullable<PaymentStatuses> PaymentStatus? sintax 只是语法糖。尝试删除 ? 并查看会发生什么(您可以添加 PaymentStatuses.NoSet = 0 ,因为 Int32 的默认值为 0)。

        祝你好运。

        【讨论】:

        • 这不起作用。我对 WCF 没有问题。如果我创建一个 DataContract 并在其中定义一个枚举,它就可以正常工作。我需要的是枚举以某种方式与 Azure 存储表一起使用。
        【解决方案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,它将你的复杂实体扁平化为扁平的 EntityProperty 字典,并以 DynamicTableEntity 的形式使它们可写入表存储。

          然后,相同的 API 将从 DynamicTableEntityEntityProperty 字典中重新组合整个复杂对象。

          这与您的问题相关,因为 ObjectFlatenerRecomposer API 支持平展通常不可写入 Azure 表存储的属性类型,例如 EnumTimeSpan、所有 Nullable 类型、ulonguint,通过转换将它们转换为可写的 EntityProperties。

          API 还处理从扁平化的EntityProperty 字典转换回原始复杂对象的过程。客户端需要做的就是告诉 API,我有这个 EntityProperty 字典,我刚刚从 Azure 表中读取(以 DynamicTableEntity.Properties 的形式),你能把它转换成这个特定类型的对象吗? API 将使用其所有属性(包括“枚举”属性及其原始正确值)重构完整的复杂对象。

          所有这些原始对象的扁平化和重组都是对客户端(API 的用户)透明地完成的。客户端不需要向 ObjectFlatenerRecomposer API 提供关于它想要编写的复杂对象的任何模式或任何知识,它只是将对象作为“对象”传递给 API 以将其展平。将其转换回来时,客户端只需提供它希望将扁平化的EntityProperty Dictionary 转换为的对象的实际类型。 API 的通用 ConvertBack 方法将简单地重构 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);
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2012-08-28
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-10-28
            • 2015-10-13
            • 2020-01-13
            相关资源
            最近更新 更多