传说中的dynamic

dynamic是个不合群、不按规则办事的家伙,可以说是个异形,但更恐怖的是它又是无所不知的,任何事情都难不了它(咳咳,它似乎与Lambda表达式是死对头)。这令人想起《死亡日记》的怪异侦探L,行为怪异而智力超人,以至于离奇的案件不得不交给了他。dynamic可以看成是一切类型的化身,但并不是仅限于此,它像《未来战士》续集里面的T-1000型液体金属的终结者。噢~~~~似乎扯的有点远了

饱经风雨而不倒的ADO.NET

ADO.NET 从来做事都有理有据,而且又异常专注于自身领域,是个professional的牛人,令人想起《美丽心灵》里面的博弈论和微分几何学领域潜心研究以致获得诺贝尔经济学奖的数学家—— 约翰·福布斯·纳什 教授(咳咳,纳什教授是个妄想型精神分裂的~~~嗯,这个以后再说)。

关于ADO.NET 的例子

1. 执行SQL语句

using (DbCommand command = connection.CreateCommand())
{
command.CommandText = "select Top 10 * from Orders";
command.CommandType = CommandType.Text; using (IDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
Console.WriteLine("OrderID: {0}, OrderDate: {1}",
reader.GetInt32(reader.GetOrdinal("OrderID")),
reader.GetDateTime(reader.GetOrdinal("OrderDate")));
}
}
}

2. 调用存储过程

         command.CommandText = "CustOrdersOrders";
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add(new SqlParameter("CustomerID", "ALFKI"));
//略去...

当 ADO.NET 遇上 dynamic

某年某月ADO.NET不幸遇到dynamic,从此循规蹈矩的生活不复存在。dynamic说它可以帮助 ADO.NET 丢掉 DataSet 的包袱,而且在不用创建数据实体的情况下,实现查询结果垮不同方法传递;更加强大的地方是可以与存储过程无缝连接,即像调用一般方法一样调用存储过程而不用写额外代码。我的神哪~~~ ADO.NET 听了dynamic一番游说后,心底下不禁惊讶一下。dynamic又说,实现刚才所说的工程只要借你手下的两大猛将 SqlConnection 和 SqlCommand 助我一臂之力即可。

dynamic真有如此奇技? ADO.NET 虽有怀疑,但它想到曾经看过一部叫《阿甘正传》的电影,里面的阿甘虽然是弱智人,但参军时练就乒乓奇技,后来还和中国国手同台竞技。想到这,ADO.NET 认为不能因为对方弱智就不相信对方的话,这是很不礼貌很不绅士的人才会做的事,所以它相信了dynamic。

dynamic 果真不负众望,三两脚猫功夫就交出成果了。

dynamic重构后的数据库操作
using (dynamic command = connection.CreateDynamicCommand())
{
//执行查询SQL
IEnumerable<dynamic> toptenOrders = command("select Top 10 * from Orders");
foreach (dynamic order in toptenOrders)
{
Console.WriteLine("OrderID: {0}, OrderDate: {1}", order.OrderID, order.OrderDate);
} //执行带参数的SQL
IEnumerable<dynamic> customerOrders = command("select * from Orders where CustomerID = @CustomerID",
CustomerID: "ALFKI");
foreach (dynamic order in customerOrders)
{
Console.WriteLine("OrderID: {0}, OrderDate: {1}", order.OrderID, order.OrderDate);
} //调用存储过程
IEnumerable<dynamic> orders = command.CustOrdersOrders(CustomerID: "ALFKI");
foreach (dynamic order in orders)
{
Console.WriteLine("OrderID: {0}, OrderDate: {1}", order.OrderID, order.OrderDate);
}
}

要知道 ADO.NET 可不是.NET菜鸟,它看到 command("select Top 10 * from Orders"); 第一感觉认为吃了dynamic药的command有可能是委托类型,而看到后面的 command.CustOrdersOrders(CustomerID: "ALFKI"); 不得不否决了前面的看法。dynamic到底是什么东西?可以这样认为,dynamic什么东西都是;也可以认为,dynamic不是什么东西!

ADO.NET 知道任何.NET写的再高深的代码在reflector下都会现出原形,通过对 command 解剖,立刻明白原来自己跟《美丽心灵》的纳什教授一样纠缠于一种不存在的幻想不能自拔,reflector告诉我们:dynamic实际上是不存在的!

还是鲁迅叔叔说的好,世界上本没有dynamic,只是微软对委托封装得太牛了,也便有了dynamic。

结语

聪明的你知道command是怎么实现了吗?不妨先想想,然后展开下面的代码看看是否与你想的一致。

点此展开代码

注:本文存储过程部分参考了微型ORM.

public static class Extensions
{
public static DynamicCommand CreateDynamicCommand(this DbConnection connection)
{
return new DynamicCommand(connection);
}
}
    /// <summary>
/// 动态Command
/// </summary>
public class DynamicCommand : DynamicObject, IDisposable
{
public DbConnection Connection { get; set; } public DynamicCommand(DbConnection connection)
{
this.Connection = connection;
} //实现SQL语句查询
public override bool TryInvoke(InvokeBinder binder, object[] args, out object result)
{
if (args.Length == 0) throw new ArgumentException("args must has value"); result = Execute(args[0].ToString(), CommandType.Text, binder.CallInfo.ArgumentNames, args.Skip(1).ToArray()); return true;
} //实现存储过程
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
{
if (binder.CallInfo.ArgumentNames.Count != binder.CallInfo.ArgumentCount)
{
throw new ArgumentException("All parameters must be named");
} result = Execute(binder.Name, CommandType.StoredProcedure, binder.CallInfo.ArgumentNames, args); return true;
} /// <summary>
/// 执行SQL查询
/// </summary>
/// <param name="commandText"></param>
/// <param name="commandType"></param>
/// <param name="names"></param>
/// <param name="args"></param>
/// <returns></returns>
private object Execute(string commandText, CommandType commandType, IEnumerable<string> names, object[] args)
{
bool manageConnectionLifespan = (this.Connection.State == ConnectionState.Closed); if (manageConnectionLifespan) this.Connection.Open(); try
{
using (var cmd = this.Connection.CreateCommand())
{
cmd.CommandType = commandType;
cmd.CommandText = commandText;
for (int i = 0; i < args.Length; i++)
{
DbParameter param = cmd.CreateParameter();
param.ParameterName = "@" + names.ElementAt(i);
param.Value = args[i] == null ? DBNull.Value : args[i];
cmd.Parameters.Add(param);
} return ExecuteList(cmd);
}
}
finally
{
if (manageConnectionLifespan)
{
this.Connection.Close();
}
}
} /// <summary>
/// 执行SQL命令,返回查询结果列表
/// </summary>
/// <param name="command"></param>
/// <returns></returns>
private static IEnumerable<dynamic> ExecuteList(DbCommand command)
{
List<DynamicEntity> resultList = new List<DynamicEntity>();
using (DbDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
DynamicEntity entity = new DynamicEntity();
for (int i = 0; i < reader.FieldCount; i++)
{
entity.SetMember(reader.GetName(i), reader.GetValue(i));
}
resultList.Add(entity);
}
}
return resultList;
} }
/// <summary>
/// 动态实体
/// </summary>
internal class DynamicEntity : DynamicObject
{
/// <summary>
/// 属性和值的字典表
/// </summary>
private Dictionary<string, object> values = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase); public override bool TryGetMember(GetMemberBinder binder, out object result)
{
if (values.ContainsKey(binder.Name))
{
result = values[binder.Name];
}
else
{
throw new System.MissingMemberException("The property " + binder.Name + " does not exist");
} return true;
} public override bool TrySetMember(SetMemberBinder binder, object value)
{
SetMember(binder.Name, value);
return true;
} public override IEnumerable<string> GetDynamicMemberNames()
{
return values.Keys;
} internal void SetMember(string propertyName, object value)
{
if (object.ReferenceEquals(value, DBNull.Value))
{
values[propertyName] = null;
}
else
{
values[propertyName] = value;
}
}
}

作者:Bruce编程的艺术世界
出处:http://coolcode.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

dynamic遇上ADO.NET的更多相关文章

  1. MVC遇上bootstrap后的ajax表单模型验证

    MVC遇上bootstrap后的ajax表单验证 使用bootstrap后他由他自带的样式has-error,想要使用它就会比较麻烦,往常使用jqueyr.validate的话只有使用他自己的样式了, ...

  2. 敏捷遇上UML-需求分析及软件设计最佳实践(郑州站 2014-6-7)

      邀请函: 尊敬的阁下:我们将在郑州为您奉献高端知识大餐,当敏捷遇上UML,会发生怎样的化学作用呢?首席专家张老师将会为您分享需求分析及软件设计方面的最佳实践,帮助您掌握敏捷.UML及两者相结合的实 ...

  3. 敏捷遇上UML—软创基地马年大会(广州站 2014-4-19)

        我们将在广州为您奉献高端知识大餐,当敏捷遇上UML,会发生怎样的化学作用呢?首席专家张老师将会为您分享需求分析及软件设计方面的最佳实践,帮助您掌握敏捷.UML及两者相结合的实战技巧. 时间:2 ...

  4. 敏捷遇上UML——软创基地马年大会(深圳站 2014-3-15)

    邀请函: 尊敬的阁下: 我们将在深圳为您奉献高端知识大餐,当敏捷遇上UML,会发生怎样的化学作用呢?首席专家张老师将会为您分享需求分析及软件设计方面的最佳实践,帮助您掌握敏捷.UML及两者相结合的实战 ...

  5. 初识genymotion安装遇上的VirtualBox问题

    想必做过Android开发的都讨厌那慢如蜗牛的 eclipse原生Android模拟器吧! 光是启动这个模拟器都得花上两三分钟,慢慢的用起来手机来调试,但那毕竟不是长久之计,也确实不方便,后来知道了g ...

  6. SQL SERVER 2008 R2 SP1更新时,遇上共享功能更新失败解决方案

    SQL SERVER 2008 R2 SP1更新时,遇上共享功能更新失败的问题,可作如下尝试: 更新失败后,在windows的[事件查看器→应用程序]中找到来源为MsiInstaller,事件ID为1 ...

  7. 当创业遇上O2O,新一批死亡名单,看完震惊了!

    当创业遇上O2O,故事就开始了,总投入1.6亿.半年开7家便利店.会员猛增至10万……2015半年过去后,很多故事在后面变成了一场创业“事故”,是模式错误还是烧钱过度?这些项目的失败能给国内创业者带来 ...

  8. LoadRunner - 当DiscuzNT遇上了Loadrunner(下) (转发)

    当DiscuzNT遇上了Loadrunner(下) 在之前的两篇文章中,基本上介绍了如何录制脚本和生成并发用户,同时还对测试报告中的几个图表做了简单的说明.今天这篇文章做为这个系列的最后一篇,将会介绍 ...

  9. LoadRunner - 当DiscuzNT遇上了Loadrunner(中) (转发)

    当DiscuzNT遇上了Loadrunner(中) 在上文中,介绍了如果录制脚本和设置脚本执行次数.如果经过调试脚本能够正常工作的话,就可以设置并发用户数并进行压力测试了. 首先我们通过脚本编辑界面上 ...

随机推荐

  1. 建立TCP连接过程

    1.服务器实例化一个ServerSocket 对象, 表示通过服务器上的端口通信. ServerSocket serverSocket = new ServerSocket(port); 2.服务器调 ...

  2. CentOS7 搭建Docker

    搭建环境 Docker支持一下的CentOS版本 CentOS 6.5 (64-bit)或者更高版本 CentOS 7 (64-bit) 搭建条件 Docker运行在CentOS 7上,要求系统64位 ...

  3. Bootstrap3基础 navbar 导航条 简单示例

      内容 参数   OS   Windows 10 x64   browser   Firefox 65.0.2   framework     Bootstrap 3.3.7   editor    ...

  4. Linux下调整ext3分区大小【转】

    本文转载自:https://blog.csdn.net/cruise_h/article/details/22403529 本文讨论如何再不丢失数据的情况下调整已有ext3分区的大小,包括: 压缩已有 ...

  5. upc组队赛1 黑暗意志【stl-map】

    黑暗意志 题目描述 在数千年前潘达利亚从卡利姆多分离之时,迷雾笼罩着这块新形成的大陆,使它不被外来者发现.迷雾同样遮蔽着这片大陆古老邪恶的要塞--雷神的雷电王座.在雷神统治时期,他的要塞就是雷电之王力 ...

  6. phpcms9-6-0 一键getshell工具

    介绍 一键化python 1.py http://xxx.com,如果是批量直接运行py文件即可 待办 [] 加入对有验证码phpcms网站的支持 [] 加入批量(已完成) 说明 依赖库的安装pip ...

  7. (zhuan) 一些RL的文献(及笔记)

    一些RL的文献(及笔记) copy from: https://zhuanlan.zhihu.com/p/25770890  Introductions Introduction to reinfor ...

  8. Hive初步使用、安装MySQL 、Hive配置MetaStore、配置Hive日志《二》

    一.Hive的简单使用 基本的命令和MySQL的命令差不多 首先在 /opt/datas 下创建数据  students.txt 1001 zhangsan 1002 lisi 1003 wangwu ...

  9. 【一】、搭建Hadoop环境----本地、伪分布式

    ##  前期准备 1.搭建Hadoop环境需要Java的开发环境,所以需要先在LInux上安装java 2.将    jdk1.7.tar.gz 和hadoop 通过工具上传到Linux服务器上 3. ...

  10. 使用CSS实现三栏自适应布局(两边宽度固定,中间自适应)

    来源:http://blog.csdn.net/cinderella_hou/article/details/52156333 所谓三列自适应布局指的是两边定宽,中间block宽度自适应.这道题在今年 ...