2012-05-22 9 views
5

私はAzureテーブルのストレージがFacebookのスタイルのフィードを作成する方法を理解しようとしていますが、エントリを取得する方法については固執しています。単一のクエリを使用してAzureテーブルストレージに複数のタイプのエンティティを取得するにはどうすればよいですか?

(私の質問はほぼhttps://stackoverflow.com/questions/6843689/retrieve-multiple-type-of-entities-from-azure-table-storageと同じですが、答えでリンクが壊れている。)

これは私の意図したアプローチです:

  1. 内のすべてのユーザーのための個人的なフィードを作成します。さまざまなタイプのエントリ(通知、ステータスの更新など)を含むことができる私のアプリケーション。私の考えは、各ユーザーのパーティションキーでグループ化されたAzureテーブルにそれらを格納することです。

  2. 同じパーティションキー内のすべてのエントリを取得し、エントリの種類に応じて異なるビューに渡します。彼らのユニークな特性を維持しながら、私は、同じベース型 のすべてのタイプのテーブル記憶を照会するにはどうすればよい

CloudTableQuery<TElement>私はエントリ固有のプロパティ(NotificationSpecificPropertyStatusUpdateSpecificProperty)およびその逆を取得しない汎用的な引数としてEntryBaseを指定した場合、入力されたエンティティが必要です。

マイエンティティ:

public class EntryBase : TableServiceEntity 
{ 
    public EntryBase() 
    { 


    } 
    public EntryBase(string partitionKey, string rowKey) 
    { 
     this.PartitionKey = partitionKey; 
     this.RowKey = rowKey; 
    } 
} 


public class NotificationEntry : EntryBase 
{ 
    public string NotificationSpecificProperty { get; set; } 
} 

public class StatusUpdateEntry : EntryBase 
{ 
    public string StatusUpdateSpecificProperty { get; set; } 
} 

飼料のための私のクエリ:

List<AbstractFeedEntry> entries = // how do I fetch all entries? 

foreach (var item in entries) 
{ 

    if(item.GetType() == typeof(NotificationEntry)){ 

     // handle notification 

    }else if(item.GetType() == typeof(StatusUpdateEntry)){ 

     // handle status update 

    } 

} 

答えて

2

これについては行くと、それはあなたに少し依存してどのように行うには、いくつかの方法があります個人的な嗜好、潜在的なパフォーマンス目標

  • 照会されたすべての型を表す合併クラスを作成します。私がStatusUpdateEntryとNotificationEntryを持っていたら、各プロパティを単一のクラスにマージするだけです。シリアライザは に自動的に正しいプロパティを入力し、他のものはnull(またはデフォルト)のままにします。エンティティに「タイプ」プロパティ(計算された、またはストレージに設定されている)も置くと、そのタイプを簡単に切り替えることができます。私はいつもテーブルエンティティからあなた自身のタイプにマッピングすることをお勧めしますので、これもうまくいきます(クラスはDTOにのみ使用されます)。
  • 例:

    [DataServiceKey("PartitionKey", "RowKey")] 
    public class NoticeStatusUpdateEntry 
    { 
        public string PartitionKey { get; set; } 
        public string RowKey { get; set; } 
        public string NoticeProperty { get; set; } 
        public string StatusUpdateProperty { get; set; } 
        public string Type 
        { 
         get 
         { 
          return String.IsNullOrEmpty(this.StatusUpdateProperty) ? "Notice" : "StatusUpate"; 
         } 
        } 
    } 
    
    • 上書きシリアライゼーションプロセス。 ReadingEntityイベントをフックすることで、これを自分で行うことができます。生のXMLを提供し、必要に応じてシリアライズすることができます。 Jai HaridasとPablo Castroは、あなたがタイプ(以下に含まれています)を知らないときにエンティティを読むためのいくつかのサンプルコードを与えました。あなたがそれについて知っている特定のタイプを読むためにそれを適応させることができます。
    • 両方のアプローチの欠点は、場合によっては必要以上に多くのデータを取得するということです。あるタイプのクエリを他のタイプと比べてどれくらいクエリしたいのかを判断する必要があります。テーブルストレージでの投影を使用することができますので、ワイヤフォーマットのサイズを縮小し、大きなエンティティや多くのエンティティを返すときに実際に高速化できます。単一の型だけを照会する必要があった場合は、RowKeyまたはPartitionKeyの一部を使用して型を指定します。これにより、一度に1つの型のみを照会できます(ただし、プロパティを使用できますがPKやRKと同じように照会の目的では効率的ではありません)。

      編集:Lucifureが指摘したように、もう1つの大きな選択肢は、その周りをデザインすることです。複数のテーブルを使用したり、並行してクエリを実行したりすることができます。タイムアウトやエラー処理の複雑さを踏まえて、それを交換する必要がありますが、必要に応じて実行可能でよくあるオプションです。一般的なエンティティの読み込み

      [DataServiceKey("PartitionKey", "RowKey")] 
      public class GenericEntity 
      { 
          public string PartitionKey { get; set; } 
          public string RowKey { get; set; } 
      
          Dictionary<string, object> properties = new Dictionary<string, object>(); 
      
          internal object this[string key] 
          { 
           get 
           { 
            return this.properties[key]; 
           } 
      
           set 
           { 
            this.properties[key] = value; 
           } 
          } 
      
          public override string ToString() 
          { 
           // TODO: append each property 
           return ""; 
          } 
      } 
      
      
          void TestGenericTable() 
          { 
           var ctx = CustomerDataContext.GetDataServiceContext(); 
           ctx.IgnoreMissingProperties = true; 
           ctx.ReadingEntity += new EventHandler<ReadingWritingEntityEventArgs>(OnReadingEntity); 
           var customers = from o in ctx.CreateQuery<GenericTable>(CustomerDataContext.CustomersTableName) select o; 
      
           Console.WriteLine("Rows from '{0}'", CustomerDataContext.CustomersTableName); 
           foreach (GenericEntity entity in customers) 
           { 
            Console.WriteLine(entity.ToString()); 
           } 
          } 
      
          // Credit goes to Pablo from ADO.NET Data Service team 
          public void OnReadingEntity(object sender, ReadingWritingEntityEventArgs args) 
          { 
           // TODO: Make these statics 
           XNamespace AtomNamespace = "http://www.w3.org/2005/Atom"; 
           XNamespace AstoriaDataNamespace = "http://schemas.microsoft.com/ado/2007/08/dataservices"; 
           XNamespace AstoriaMetadataNamespace = "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"; 
      
           GenericEntity entity = args.Entity as GenericEntity; 
           if (entity == null) 
           { 
            return; 
           } 
      
           // read each property, type and value in the payload 
           var properties = args.Entity.GetType().GetProperties(); 
           var q = from p in args.Data.Element(AtomNamespace + "content") 
                 .Element(AstoriaMetadataNamespace + "properties") 
                 .Elements() 
             where properties.All(pp => pp.Name != p.Name.LocalName) 
             select new 
             { 
              Name = p.Name.LocalName, 
              IsNull = string.Equals("true", p.Attribute(AstoriaMetadataNamespace + "null") == null ? null : p.Attribute(AstoriaMetadataNamespace + "null").Value, StringComparison.OrdinalIgnoreCase), 
              TypeName = p.Attribute(AstoriaMetadataNamespace + "type") == null ? null : p.Attribute(AstoriaMetadataNamespace + "type").Value, 
              p.Value 
             }; 
      
           foreach (var dp in q) 
           { 
            entity[dp.Name] = GetTypedEdmValue(dp.TypeName, dp.Value, dp.IsNull); 
           } 
          } 
      
      
          private static object GetTypedEdmValue(string type, string value, bool isnull) 
          { 
           if (isnull) return null; 
      
           if (string.IsNullOrEmpty(type)) return value; 
      
           switch (type) 
           { 
            case "Edm.String": return value; 
            case "Edm.Byte": return Convert.ChangeType(value, typeof(byte)); 
            case "Edm.SByte": return Convert.ChangeType(value, typeof(sbyte)); 
            case "Edm.Int16": return Convert.ChangeType(value, typeof(short)); 
            case "Edm.Int32": return Convert.ChangeType(value, typeof(int)); 
            case "Edm.Int64": return Convert.ChangeType(value, typeof(long)); 
            case "Edm.Double": return Convert.ChangeType(value, typeof(double)); 
            case "Edm.Single": return Convert.ChangeType(value, typeof(float)); 
            case "Edm.Boolean": return Convert.ChangeType(value, typeof(bool)); 
            case "Edm.Decimal": return Convert.ChangeType(value, typeof(decimal)); 
            case "Edm.DateTime": return XmlConvert.ToDateTime(value, XmlDateTimeSerializationMode.RoundtripKind); 
            case "Edm.Binary": return Convert.FromBase64String(value); 
            case "Edm.Guid": return new Guid(value); 
      
            default: throw new NotSupportedException("Not supported type " + type); 
           } 
          } 
      
    +2

    これは非常に古い答えであることを人々が理解してくれることを願っています。汎用または動的エンティティは、ストレージSDKで直接サポートされています。 – dunnry

    1

    別のオプションは、もちろん、テーブルごとに1つだけのエンティティタイプを持って並列にテーブルを照会し、タイムスタンプによってソートされた結果をマージすることです。 長期的には、これは拡張性と保守性に関してより慎重な選択であることがわかります。

    また、非共通データが明示的に入力されておらず、代わりに辞書を介して保持される「dunnry」で概説されているように、一般的なエンティティを使用する必要があります。

    私は辞書から/への持続を含むAzureテーブルストレージの上に追加の抽象化をサポートし、代替のAzureテーブル・ストレージ・クライアント、Lucifureスタッシュを、書かれている、そしてそれはあなたが追求したい方向であれば、あなたのような状況で働くこと。

    Lucifure Stashは、大きなデータ列> 64K、配列&リスト、列挙型、コンポジットキー、アウトオブボックスのシリアル化、ユーザー定義のモーフィング、パブリックプロパティとプライベートプロパティ、フィールドなどをサポートしています。それはhttp://www.lucifure.comまたはNuGet.comで個人的に使用するために無料で利用できます。

    編集:CodePlex

    1

    クエリ内のエンティティタイプとして使用DynamicTableEntity。それはあなたが調べることができる特性の辞書を持っています。どのエンティティタイプも返すことができます。

    関連する問題