传说中的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. 存根类(stub) 是什么意思?有什么作用?(转)

    存根类是一个类,它实现了一个接口,但是实现后的每个方法都是空的.  它的作用是:如果一个接口有很多方法,如果要实现这个接口,就要实现所有的方法.但是一个类从业务来说,可能只需要其中一两个方法.   如 ...

  2. [c/c++] programming之路(1)、编写程序打开记事本、计算器等

    一.命令行启动程序 通过命令行关闭程序:taskkill /f /im 程序名.exe 二.打开记事本.计算器 #include <stdlib.h> void main(){ syste ...

  3. php 带省略号的分页

    原文链接:https://blog.csdn.net/u011060253/article/details/25308455 $curpage = isset($_GET[; $page = new ...

  4. Java——List:list.add(index, element)和list.set(index, element)的区别

    add(index, element) 含义:在集合索引为index的位置上增加一个元素element,集合list改变后list.size()会增加1 用法 testList.add(index, ...

  5. linux内核中的DMI是什么?

    答: 桌面管理接口(Desktop Management Interface).是用来获取硬件信息的,在内核中有一个配置项CONFIG_DMI用来添加此功能到内核中!

  6. 放棋子|2012年蓝桥杯B组题解析第七题-fishers

    (13')放棋子 今有 6 x 6 的棋盘格.其中某些格子已经预先放好了棋子.现在要再放上去一些,使得:每行每列都正好有3颗棋子.我们希望推算出所有可能的放法.下面的代码就实现了这个功能. 初始数组中 ...

  7. SPOJ 694 DISUBSTR - Distinct Substrings

    思路 求本质不同的子串个数,总共重叠的子串个数就是height数组的和 总子串个数-height数组的和即可 代码 #include <cstdio> #include <algor ...

  8. P4721【模板】分治 FFT

    瞎扯 虽然说是FFT但是还是写了一发NTT(笑) 然后忘了IDFT之后要除个n懵逼了好久 以及递归的时候忘了边界无限RE 思路 朴素算法 分治FFT 考虑到题目要求求这样的一个式子 \[ F_x=\S ...

  9. it做形式主语的句子

    1. it was considerate of you to visit my mother every day and (to) bring me your notes to help me wi ...

  10. Twitter REST API, Streaming API

    原文链接           用Twitter自己的话来说:   REST API The REST API provides simple interfaces for most Twitter f ...