How to access table storage entities without knowing the schema

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Services.Client;
using System.Data.Services.Common;
using Microsoft.Samples.ServiceHosting.StorageClient;
using System.Xml.Linq;
using System.Xml;


namespace AccessTableStorageUsingGenericEntiry
{
    class Program
    {
        static void Main(string[] args)
        {
            test a = new test();
            a.TestGenericTable();
        }

    }

    [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()
        {
            StringBuilder sb = new StringBuilder();
            foreach (KeyValuePair<string, object> a in properties)
            {
                sb.AppendLine(a.Key + ":" + a.Value);
            }
            return sb.ToString();
        }
    }

    class GenericEntityDataServiceContext : TableStorageDataServiceContext
    {
        public GenericEntityDataServiceContext(StorageAccountInfo accountInfo)
            : base(accountInfo)
        {
        }

        public IQueryable<GenericEntity> GenericEntities
        {
            get
            {
                return this.CreateQuery<GenericEntity>("GenericEntities");
            }
        }
    }

    public class test
    {
       public void TestGenericTable()
        {
            StorageAccountInfo account = new StorageAccountInfo(new Uri("http://127.0.0.1:10002/"), true, "devstoreaccount1", "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==");
            TableStorage table1 = TableStorage.Create(account);
            var ctx = table1.GetDataServiceContext();
            ctx.IgnoreMissingProperties = true;
            ctx.ReadingEntity += new EventHandler<ReadingWritingEntityEventArgs>(OnReadingEntity);

            //"Messages" is a table name in table storage   
            var customers = from o in ctx.CreateQuery<GenericEntity>("Messages") select o;

            Console.WriteLine("Rows from '{0}'", "Messages");
            foreach (GenericEntity entity in customers)
            {
                Console.WriteLine(entity.ToString());
            }
        }


        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);
            }
        } 
    }

}

posted on 2009-02-11 14:45  Yang - Windows Azure  阅读(370)  评论(0编辑  收藏  举报

导航