`

当 ADO.NET 遇上 dynamic

阅读更多


作者: CoolCode 发表于 2010-07-18 17:46 原文链接 阅读: 778 评论: 13

传说中的dynamic

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

9MV9FQGYXA1AJVJR{A%RV}B

饱经风雨而不倒的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;
        }
    }
}

评论: 13 查看评论 发表评论

百度期待您的加盟


最新新闻:
· 微软不为外界所知的十件趣事(2010-07-18 22:58)
· 中国第2季搜索引擎市场规模达26亿 百度破70%(2010-07-18 22:54)
· Facebook用户数下周达5亿 邀请用户共享故事(2010-07-18 22:49)
· 开源的可视化编辑器 KindEditor 3.5.1 发布(2010-07-18 22:35)
· WordPress 陷入开源‘边界’之争(2010-07-18 17:47)

编辑推荐:揭秘Facebook背后的那些软件

网站导航:博客园首页  个人主页  新闻  闪存  小组  博问  社区  知识库

分享到:
评论

相关推荐

    ADO.NET 4从入门到精通

    《ADO.NET 4从入门到精通》主要内容简介:ADO.NET是windows开发平台上的核心数据技术之一。《ADO.NET 4从入门到精通》是microsoft ADO.NET 4的入门教程,旨在帮助visual basic和c#开发人员了解ADO.NET及相关技术的...

    ADO.Net助手V1.00---一个获取ADO.Net连接字符串,测试SQL命令的辅助软件

    ADO.Net助手是一个获取ADO.Net连接字符串(支持Access,SQLite,SQLServer,MySQL和ORACLE),测试SQL命令,存储过程和数据库之间互导数据的辅助软件。ADO.Net助手还可以用来以插入SQL语句形式导出导入记录,目前提供了...

    ADO.NET考试上机题

    ADO.NET考试上机题ADO.NET考试上机题ADO.NET考试上机题ADO.NET考试上机题ADO.NET考试上机题ADO.NET考试上机题ADO.NET考试上机题ADO.NET考试上机题ADO.NET考试上机题ADO.NET考试上机题ADO.NET考试上机题ADO.NET考试...

    Professional ADO .NET Programming

    Professional ADO .NET Programming Professional ADO .NET Programming Professional ADO .NET Programming Professional ADO .NET Programming

    ADO.NET sql、LINQ to sql、ADO.NET Entity Framework(EF)数据库连接性能比较

    数据ADO.NET sql、LINQ to sql、ADO.NET Entity Framework(EF)数据库连接性能比较,主要比较了插入与读取的时间,读取里可以进行模糊检索

    基于ADO.NET的用户登陆与注册系统

    摘要:基于ASP.NET的WEB应用程序项目,使用程序语言C#,利用ADO.NET访问数据库,实现一个简易的用户登陆注册系统。主要实现的功能有用户登陆、用户注册、找回密码,... 关键字:ASP.NET;ADO.NET;WEB;vs2010;数据库

    ADO.NET自己封装SqlHelper类

    ADO.NET自己封装SqlHelper类 1、简单封装 2、传递参数封装 3、参数可变封装

    ADO.NET数据库访问技术详细资料

    ADO.NET是与数据库访问操作有关的对象模型的集合,它基于Microsoft的.NET Framework,在很大程度上封装了数据库访问和数据操作的动作。 ADO.NET同其前身ADO系列访问数据库的组件相比,做了以下两点重要改进: ...

    ADO.NET 高级编程

    ADO.NET 高级编程,深入剖析ADO.NET类

    ado.net操作oracle简单参数化sql操作

    关于ado.net简单的参数化查询,操作的是oracle数据库!关于ado.net简单的参数化查询,操作的是oracle数据库!

    ADO.NET本质论

    讲解了数据结构,演示了如何用ADO.NET来解决具体的数据访问问题。重点讨论了ADO.NET如何有效地平衡"功能的泛化"和"执行效率",以及它如何解决对扩展性、并发性和可靠性的要求。针对其他数据访问API(包括OLE DB,ADO...

    Microsoft ADO.NET Step by Step

    Table of Contents Microsoft ADO.NET Step by Step Introduction Part I - Getting Started with ADO.NET Chapter 1 - Getting Started with ADO.NET ...

    ADO.Net数据库访问(代码示例)

    ADO.Net数据库访问(代码示例),介绍了ADO.Net数据库访问的核心技术

    Codesmith ADO.NET 模版

    Codesmith ADO.NET 模版Codesmith ADO.NET 模版Codesmith ADO.NET 模版Codesmith ADO.NET 模版Codesmith ADO.NET 模版Codesmith ADO.NET 模版

    学生管理系统+ADO.NET+SQL2005

    学生管理系统源码,ADO.NET进行增删改查学生基本和系别信息,适合毕业设计。

    ADO.NET高级编程

    ADO.NET是Microsoft最新推出的数据访问技术。作为.NET框架的一部分,ADO.NET绝不仅仅是前一版本ADO的简单升级。ADO.NET提供了一组.NET类,这些类不仅可以帮助我们对各种数据源进行高效访问,使我们能够对数据...

    ADO.NET 4从入门到精通源代码

    ADO.NET 4从入门到精通源代码 里面有 未完成的和已完成的 源代码示例

    Pro ADO.NET Data Services: Working with RESTful Data

    Pro ADO.NET Data Services: Working with RESTful Data Paperback: 336 pages Publisher: Apress; 1 edition (December 2, 2008) Language: English ISBN-10: 143021614X ISBN-13: 978-1430216148 Format: PDF You...

    ADO.net操作数据库总结

    ADO.net操作数据库总结,包括SqlConnection、SqlCommand等

    ado.net本质论

    ado.net本质论ado.net本质论ado.net本质论ado.net本质论ado.net本质论

Global site tag (gtag.js) - Google Analytics