`

当 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+SQL2005

    《基于ADO.NET与SQL2005的学生管理系统详解》 在信息技术日新月异的今天,学生管理系统已经成为教育机构日常管理的重要工具。本系统利用ADO.NET技术和SQL Server 2005数据库,实现了对学生的全面信息化管理,为教育...

    ADO.NET 4从入门到精通

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

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

    本文将深入探讨三种常见的.NET框架下的数据库访问技术:ADO.NET SQL、LINQ to SQL以及ADO.NET Entity Framework(EF),并重点分析它们在数据库连接性能上的差异,特别是在插入和读取操作,包括模糊检索方面的表现。...

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

    ADO.NET 4是微软.NET Framework 4的一部分,它提供了一组用于访问数据库的类和接口。这个技术允许开发者高效地创建、操作和管理数据存储,无论是关系型数据库还是其他类型的数据源。本压缩包文件“ADO.NET 4从入门到...

    ADO.NET 全面解析ADO.NET

    ADO.NET是Microsoft开发的一种用于访问关系数据库的数据访问技术,它为.NET Framework应用程序提供了一套全面的数据访问组件。本文将深入探讨ADO.NET的核心概念、对象模型和数据操作。 首先,我们来看ADO.NET的设计...

    ado.net面试题

    ADO.NET 是微软为.NET Framework 设计的一种全新的数据库访问技术,它是对传统ADO(ActiveX Data Objects)的升级,旨在提供更高效、更易用的数据访问接口。ADO.NET 的设计核心是面向数据集而非数据库,这使得它更适合...

    ADO.NET教程(适合新手)

    ADO.NET的数据可以方便地绑定到Windows Forms或ASP.NET控件上,实现数据的可视化展示和编辑。 8. **错误处理和异常处理** 在进行数据库操作时,应始终考虑错误处理。当发生错误时,ADO.NET会抛出异常,可以捕获...

    ADO.NET本质论.rar

    ADO.NET是微软开发的一种用于访问数据的框架,它在.NET Framework中扮演着核心角色,为开发者提供了高效、灵活的数据访问接口。"ADO.NET本质论"这本书深入探讨了ADO.NET的内在原理和实际应用,旨在帮助读者理解并...

    ADO.NET核心技术(我看过最好的ADO。NET书)

    ### ADO.NET核心技术详解 #### 一、ADO.NET概述 ADO.NET是一组包含在.NET框架中的库,专门用于在.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考试上机题ADO.NET考试...

    《ADO.NET专业项目实例开发》源代码

    ADO.NET是微软.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项目 借阅图书

    《自做的ADO.NET项目——借阅图书》 在信息技术领域,数据库管理是不可或缺的一部分,而ADO.NET作为.NET框架中用于数据库交互的重要组件,为开发者提供了高效、强大的数据访问能力。本项目“借阅图书”正是基于ADO...

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

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

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

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

    ADO.NET官方参考文档2021-09.pdf

    ADO.NET 是 .NET Framework 中用于访问关系数据库的关键组件,它提供了与各种数据源(如 SQL Server、Oracle 等)交互的灵活性。在2021-09版的官方参考文档中,主要关注了DataSet、DataTable、DataView这三个核心类...

    ADO.NET本质论.pdf

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

    ado.net简介(flash)

    - 虽然不在原始的ADO.NET中,但后来发展出的Entity Framework成为了.NET平台上的主流ORM(对象关系映射)工具,简化了与数据库的交互,允许开发者使用面向对象的方式操作数据。 在实际开发中,ADO.NET通常与其他...

    ADO.NET数据库访问技术案例教程

    ADO.NET是微软.NET框架下的一种数据访问技术,用于与各种关系型数据库进行交互。它提供了一组组件和服务,使得开发者可以高效、灵活地存取和处理数据。在本"ADO.NET数据库访问技术案例教程"中,我们将深入探讨ADO...

Global site tag (gtag.js) - Google Analytics