dynamic遇上ADO.NET
传说中的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的更多相关文章
- MVC遇上bootstrap后的ajax表单模型验证
MVC遇上bootstrap后的ajax表单验证 使用bootstrap后他由他自带的样式has-error,想要使用它就会比较麻烦,往常使用jqueyr.validate的话只有使用他自己的样式了, ...
- 敏捷遇上UML-需求分析及软件设计最佳实践(郑州站 2014-6-7)
邀请函: 尊敬的阁下:我们将在郑州为您奉献高端知识大餐,当敏捷遇上UML,会发生怎样的化学作用呢?首席专家张老师将会为您分享需求分析及软件设计方面的最佳实践,帮助您掌握敏捷.UML及两者相结合的实 ...
- 敏捷遇上UML—软创基地马年大会(广州站 2014-4-19)
我们将在广州为您奉献高端知识大餐,当敏捷遇上UML,会发生怎样的化学作用呢?首席专家张老师将会为您分享需求分析及软件设计方面的最佳实践,帮助您掌握敏捷.UML及两者相结合的实战技巧. 时间:2 ...
- 敏捷遇上UML——软创基地马年大会(深圳站 2014-3-15)
邀请函: 尊敬的阁下: 我们将在深圳为您奉献高端知识大餐,当敏捷遇上UML,会发生怎样的化学作用呢?首席专家张老师将会为您分享需求分析及软件设计方面的最佳实践,帮助您掌握敏捷.UML及两者相结合的实战 ...
- 初识genymotion安装遇上的VirtualBox问题
想必做过Android开发的都讨厌那慢如蜗牛的 eclipse原生Android模拟器吧! 光是启动这个模拟器都得花上两三分钟,慢慢的用起来手机来调试,但那毕竟不是长久之计,也确实不方便,后来知道了g ...
- SQL SERVER 2008 R2 SP1更新时,遇上共享功能更新失败解决方案
SQL SERVER 2008 R2 SP1更新时,遇上共享功能更新失败的问题,可作如下尝试: 更新失败后,在windows的[事件查看器→应用程序]中找到来源为MsiInstaller,事件ID为1 ...
- 当创业遇上O2O,新一批死亡名单,看完震惊了!
当创业遇上O2O,故事就开始了,总投入1.6亿.半年开7家便利店.会员猛增至10万……2015半年过去后,很多故事在后面变成了一场创业“事故”,是模式错误还是烧钱过度?这些项目的失败能给国内创业者带来 ...
- LoadRunner - 当DiscuzNT遇上了Loadrunner(下) (转发)
当DiscuzNT遇上了Loadrunner(下) 在之前的两篇文章中,基本上介绍了如何录制脚本和生成并发用户,同时还对测试报告中的几个图表做了简单的说明.今天这篇文章做为这个系列的最后一篇,将会介绍 ...
- LoadRunner - 当DiscuzNT遇上了Loadrunner(中) (转发)
当DiscuzNT遇上了Loadrunner(中) 在上文中,介绍了如果录制脚本和设置脚本执行次数.如果经过调试脚本能够正常工作的话,就可以设置并发用户数并进行压力测试了. 首先我们通过脚本编辑界面上 ...
随机推荐
- bzoj 2820 YY的GCD - 莫比乌斯反演 - 线性筛
Description 神犇YY虐完数论后给傻×kAc出了一题给定N, M,求1<=x<=N, 1<=y<=M且gcd(x, y)为质数的(x, y)有多少对kAc这种 傻×必 ...
- 数据库 --- 4 多表查询 ,Navicat工具 , pymysql模块
一.多表查询 1.笛卡儿积 查询 2.连接 语法: ①inner 显示可构成连接的数据 mysql> select employee.id,employee.name,department ...
- selinux权限问题【转】
本文转载自:https://blog.csdn.net/u011386173/article/details/83339770 版权声明:本文为博主原创文章,未经博主允许不得转载. https://b ...
- 转载:Systemd 命令
目录 一.由来 二.Systemd 概述 三.系统管理 3.1 systemctl 3.2 systemd-analyze 3.3 hostnamectl 3.4 localectl 3.5 time ...
- MySQL 命令操作数据表
MySQL 命令操作数据表 1.查看表信息 desc hs_user_credit_info; 2.新增表字段 alter table hs_credit_order add search_relat ...
- sudo用法记录
使用root用户,visudo命令(实际是编辑/etc/sudoers文件),用法和vim一样,末行模式:wq退出,如还有提示,使用大写"Q"保存退出,小写"e" ...
- 【拼接属性查询方式】MySql某一列属性值为拼接时的查询方式
数据库中某一列的值为 使用IN查询是无法查询到数据的,只能查询到IN(2)或者IN(2,3) 查询结果: , style_id) 正确方式:使用FIND_IN_SET函数 , style_id) , ...
- [转] J2EE基础知识
Servlet总结 阐述Servlet和CGI的区别? CGI的不足之处: Servlet的优点: Servlet接口中有哪些方法及Servlet生命周期探秘 get和post请求的区别 什么情况下调 ...
- html 之 padding,margin
margin:对象挤压外界 padding:对象挤压自身 例如: td使用margin 对table而言没有任何效果,但使用padding是对table内部的挤压,若是table空间不够,则会扩大ta ...
- P3232 [HNOI2013]游走
吐槽 傻了傻了,对着题解改了好长时间最后发现是自己忘了调用高斯消元了... 思路 期望题,分配编号,显然编号大的分给贡献次数小的,所以需要知道每个边被经过次数的期望 然后边被经过的次数的期望就是连接的 ...