在之前的一篇文章中提到,storage类库中包含一个可以用来动态获取Azure table storage 表结构的类-DynamicTableEntity。

我们可以通过这个类,我们无需为每一个表提前声明一个class,也能够对其进行操作。

但在我们要添加Entity到表中的时候会感觉到一点不舒服

以下我所希望使用的该类的方式:

dynamic entity = new DynamicTableEntity();
entity.Name=”sam”;
entity.Gender=true;

这样的形式

而实际代码却是

DynamicTableEntity entity1 = new DynamicTableEntity();
Dictionary<string, EntityProperty> data1 = new Dictionary<string, EntityProperty>();
data1.Add("Name", new EntityProperty("Sam"));
data1.Add("Gender", new EntityProperty(true));
data1.Add("Age", new EntityProperty(18));
entity1.Properties = data1;
entity1.PartitionKey = "Partition1";
entity1.RowKey = "1";
UserDataList.Add(entity1);

  

身为一个以dynamic开头的类居然不能够用dynamic关键字来初始化它,在实例化一个DynamicTableEntity类的时候居然要如此麻烦,实在让人不爽。

所以, 经过一番研究,发现了一个可以支持动态扩展的类,为了与DynamicTableEntity区分开来,所以取名DynamicObjectTableEntity。它实现了DynamicTableEntity相同的功能,而且继承了DynamicObject,从而具有动态语言的特性,更加方便 使用。

而且动态语言扩展一直以来除了在linq中使用比较多以外,其它地方基本看不到。这里正好通过对dynamicTableEntity的改造可以加深对动态语言扩展的理解。

实现代码如下:

public class DynamicObjectTableEntity : DynamicObject,ITableEntity
{
#region DynamicTableEntity's code
// Methods
public DynamicObjectTableEntity()
{
this.Properties = new Dictionary<string, EntityProperty>();
} public DynamicObjectTableEntity(string partitionKey, string rowKey) : this(partitionKey, rowKey, DateTimeOffset.MinValue, null, new Dictionary<string, EntityProperty>())
{
} public DynamicObjectTableEntity(string partitionKey, string rowKey, string etag, IDictionary<string, EntityProperty> properties) : this(partitionKey, rowKey, DateTimeOffset.MinValue, etag, properties)
{
} internal DynamicObjectTableEntity(string partitionKey, string rowKey, DateTimeOffset timestamp, string etag, IDictionary<string, EntityProperty> properties)
{
//CommonUtility.AssertNotNull("partitionKey", partitionKey);
//CommonUtility.AssertNotNull("rowKey", rowKey);
//CommonUtility.AssertNotNull("properties", properties);
this.PartitionKey = partitionKey;
this.RowKey = rowKey;
this.Timestamp = timestamp;
this.ETag = etag;
this.Properties = properties;
} public void ReadEntity(IDictionary<string, EntityProperty> properties, OperationContext operationContext)
{
this.Properties = properties;
} public IDictionary<string, EntityProperty> WriteEntity(OperationContext operationContext)
{
return this.Properties;
} // Properties
public string ETag { get; set; } public EntityProperty this[string key]
{
get
{
return this.Properties[key];
}
set
{
this.Properties[key] = value;
}
} public string PartitionKey { get; set; } public IDictionary<string, EntityProperty> Properties { get; set; } public string RowKey { get; set; } public DateTimeOffset Timestamp { get; set; } #endregion #region override DynamicObject's mehtods
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
if (!Properties.ContainsKey(binder.Name))
Properties.Add(binder.Name, ConvertToEntityProperty(binder.Name, null));
result = Properties[binder.Name];
return true;
} public override bool TrySetMember(SetMemberBinder binder, object value)
{
EntityProperty property = ConvertToEntityProperty(binder.Name, value); if (Properties.ContainsKey(binder.Name))
Properties[binder.Name] = property;
else
Properties.Add(binder.Name, property); return true;
} /// <summary>
/// Convert object value to EntityProperty.
/// </summary>
private EntityProperty ConvertToEntityProperty(string key, object value)
{
if (value == null) return new EntityProperty((string)null);
if (value.GetType() == typeof(byte[]))
return new EntityProperty((byte[])value);
if (value.GetType() == typeof(bool))
return new EntityProperty((bool)value);
if (value.GetType() == typeof(DateTimeOffset))
return new EntityProperty((DateTimeOffset)value);
if (value.GetType() == typeof(DateTime))
return new EntityProperty((DateTime)value);
if (value.GetType() == typeof(double))
return new EntityProperty((double)value);
if (value.GetType() == typeof(Guid))
return new EntityProperty((Guid)value);
if (value.GetType() == typeof(int))
return new EntityProperty((int)value);
if (value.GetType() == typeof(long))
return new EntityProperty((long)value);
if (value.GetType() == typeof(string))
return new EntityProperty((string)value);
throw new Exception("This value type" + value.GetType() + " for " + key);
throw new Exception(string.Format("This value type {0} is not supported for {1}", key));
} /// <summary>
/// Get the edm type, if the type is not a edm type throw a exception.
/// </summary>
private Type GetType(EdmType edmType)
{
switch (edmType)
{
case EdmType.Binary:
return typeof(byte[]);
case EdmType.Boolean:
return typeof(bool);
case EdmType.DateTime:
return typeof(DateTime);
case EdmType.Double:
return typeof(double);
case EdmType.Guid:
return typeof(Guid);
case EdmType.Int32:
return typeof(int);
case EdmType.Int64:
return typeof(long);
case EdmType.String:
return typeof(string);
default: throw new TypeLoadException(string.Format("not supported edmType:{0}", edmType));
}
} #endregion
}

 

在使用了如下类之后,我们就可以用我预期的代码来操作table 了

代码如下:

static void Main(string[] args)
{
var connectionString = "DefaultEndpointsProtocol=https;AccountName=[Account];AccountKey=[Key]";
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(connectionString);
try
{
var client = storageAccount.CreateCloudTableClient();
var table = client.GetTableReference("ShortMessages");
table.CreateIfNotExists();
dynamic entity = new DynamicObjectTableEntity("default", DateTime.Now.ToShortTimeString()); entity.Name = "pete";
entity.Message = "Hello";
table.Execute(TableOperation.Insert(entity));
Console.WriteLine("insert successfully!");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.Read();
}

  

示例参考MSDN:http://code.msdn.microsoft.com/Dynamic-TableServiceEntity-151d661f

 

 

Azure Table storage 之改进DynamicTableEntity类为其添加动态语言扩展的更多相关文章

  1. Windows Azure Table storage 之 动态Table类 DynamicTableEntity

    在一般情况下,当我们在.net中使用Azure table storage的时候都会为该表建立一个TableEntity的派生类,如下所示. public class CustomerEntity : ...

  2. Azure Table storage 基本用法 -- Azure Storage 之 Table

    Azure Storage 是微软 Azure 云提供的云端存储解决方案,当前支持的存储类型有 Blob.Queue.File 和 Table,其中的 Table 就是本文的主角 Azure Tabl ...

  3. 自定义 Azure Table storage 查询过滤条件

    本文是在Azure Table storage 基本用法一文的基础上,介绍如何自定义 Azure Table storage 的查询过滤条件.如果您还不太清楚 Azure Table storage ...

  4. Windows Azure Table Storage 解决 Guid 查询问题

    在使用 Windows Azure Table Storage 的 CloudTableClient 对Azure 进行数据查询时,会发现在自定义类的Guid类型始终无法去成功查询出数据,对比发现 G ...

  5. Azure Table Storage(一) : 简单介绍

    Azure Table Storage是什么: Azure Table Storage是隶属于微软Azure Storage这个大服务下的一个子服务, 这个服务在Azure上算是老字号了, 个人大概在 ...

  6. Azure 基础:Table storage

    Azure Storage 是微软 Azure 云提供的云端存储解决方案,当前支持的存储类型有 Blob.Queue.File 和 Table.其中的 Table 就是本文的主角 Azure Tabl ...

  7. Azure 基础:自定义 Table storage 查询条件

    本文是在 <Azure 基础:Table storage> 一文的基础上介绍如何自定义 Azure Table storage 的查询过滤条件.如果您还不太清楚 Azure Table s ...

  8. [Windows Azure] How to use the Table Storage Service

    How to use the Table Storage Service version 1.7 version 2.0 This guide will show you how to perform ...

  9. Azure Storage 系列(四)在.Net 上使用Table Storage

    一,引言 今天我们就不多说废话了,直接进入正题,Azure Table Storage.开始内容之前,我们先介绍一下Azure Table Storage. 1,什么是Azure Table Stor ...

随机推荐

  1. mysql相似于oracle的to_char() to_date()方法

    mysql日期和字符相互转换方法, date_format(date,'%Y-%m-%d')  -------------->oracle中的to_char(); str_to_date(dat ...

  2. js通过sessionStorage实现的返回上一页

    通常,我们都会使用比较熟悉的javascript:history.go(-1)来实现返回上一页,此种方法有一个问题就是返回上一页后不能刷新当前页面,给我们的开发带来了一定的不便,显然有时这种方法就不是 ...

  3. display:inline、block、inline-block 的区别

    一.块级元素 与  行级元素 要理解display:inline.block.inline-block的区别,需要先了解HTML中的块级(block)元素和行级(inline)元素的特点,行内元素也叫 ...

  4. android开发期间使用真机调试但系统无法识别出真机

    前言 前些天重装了系统,好不容易把所有的软件装好,结果发现打开android studio真机调试却出了问题. 一.症状: 1.手机端设置完全没问题(打开了调试模式......) 2.电脑端右下角不出 ...

  5. mysql双主复制总结

    双主复制: 1).在两台服务器上各自建立一个具有复制权限的用户: 2).修改配置文件: # 主服务器A上 [mysqld] server-id = 10 log-bin = mysql-bin rel ...

  6. mysql 的2个关于事务和安全性的参数

    innodb_flush_log_at_trx_commit:(mysql写事物日志的方式) 0 log buffer 会每秒写入到日志文件中,并刷新到磁盘  (提交方式与事物无关,性能最好) 1 事 ...

  7. Js练笔——用循环和递归实现追踪对象深度(循环引用关系不考虑)

    function reobs(obj){ //返回对象中对象属性组成的数组 var a=[]; var b=[]; for(it in obj){ a.push(it); } for(var i=0; ...

  8. 2016huasacm暑假集训训练三 B-Frogger

    题目链接:http://acm.hust.edu.cn/vjudge/contest/123674#problem/B 题意:一只青蛙在湖中一颗石头上, 它想去有另一只青蛙的石头上,但是 湖里的水很脏 ...

  9. CVTRES : fatal error CVT1100 , fatal error LNK1123:

    CVTRES : fatal error CVT1100: duplicate resource. type:DIALOG, name:901, language:0x0804LINK : fatal ...

  10. prim算法

    最小生成树 一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边.最小生成树可以用kruskal(克鲁斯卡尔)算法或prim(普里姆)算法 ...