在上一篇文章中介绍了.NET下使用Oracle数据提供程序访问Oracle的方法以及较老的数据库访问方式 ,ODBC,DAO,RDO等。总的说ODBC的出现使得程序员不必在关注与特定的数据库接口进行编程。而是利用数 据库驱动来隐藏了不同数据库的差异,提供了统一的数据库编程接口。但是ODBC是C语言风格的接口,对 于VB,ASP等程序无法直接使用,于是出现了DAO.RDO等面向对象的接口供程序员使用。

 

一 OLE DB

 

ODBC,DAO的表现在关系型数据库上已经很好了,但是随着数据的发展,非关系行的数据Excel,XML, 邮件等的出现,使得ODBC无法对这些数据进行访问。而随着COM的发展,组件模型的思想也进入了数据库 中,于是出现了OLE DB。全名是Object Linking and Embedding DataBase。对象连接与嵌入,简称OLE技 术。OLE 不仅是桌面应用程序集成,而且还定义和实现了一种允许应用程序作为软件“对象 ”(数据集合和操作数据的函数)彼此进行“连接”的机制,这种连接机制和协议称为部 件对象模型。

 

OLEDB      OLEDB

OLE DB 建立于 ODBC 之上,并将此技术扩展为提供更高级数据访问接口的组件结构。此结构对企业中 及 Internet 上的 SQL、非 SQL 和非结构化数据源提供一致的访问。OLE DB 由三个组件构成:数据使用者(例如,一个应用程序);包 含并公开数据的数据提供程序以及处理并传输数据的服务组件(例如,查询处理器、游标引擎)。OLE DB 是一个针对 SQL 数据源和非 SQL 数据源(例如,邮件和目录)进行操作的基于COM的 API。

OLEDB的特点是他的多层组件结构,而最重要的就是她的数据提供程序,正式他隐藏了数据源的不同特 征,使得应用程序可以访问关系和非关系型数据库。而各层之间通过Com通信。

继续阅读

最近做一个ASP.NET性能优化的小项目,目前还是在搭建测试环境,服务器使用WINDOWS2008,有2台AP server ,通过双网卡进行NLB组成集群,一台DB服务器,使用的是ORACLE 11g,然后客户还指出要使用ODP.NET。因为大多是使用的是SQL SERVER数据库,而以前接触ORACLE9i,10G时都是在Linux环境下,所以不太了解这个ODP.NET是个什么。 然后就查了查,发现好多东西都了解的不是很清楚,所以写篇文章吧了解到的写下来,可能有点杂碎吧。关于集群方面的等搭建完了在介绍介绍。

一 ODP.NET

 

ODP.NET全名是Oracle Data Provider,是Oracle发布的供.NET程序访问Oracle数据库的ADO.NET组件,比微软自带的Oracle组件性能好,更可以访问UDT(User Defined Type)类型,Procedure,REF等等高级Oracle特性。目前最新的版本是11g。在Oracle的官方网站可以下载。不过我都是跟随ODAC包一起下载下来的,关于ODAC后面介绍吧。

使用过.NET连接Oracle的都知道。一般都是使用OLEDB或者是.NET中提供的OracleClient来进行连接。我记得在.NET1.0中好像是没有包含OracleClient,需要单独下载,然后1.1中就有了,记得当时MSDN上有写。而微软也宣称,从.NET4.0开始放弃对OracleClient的支持,但不会删除,标记为不建议使用。 所以可以使用ORACLE提供的ADO.NET访问组件ODP.NET,组件的名字为OracleDataAccess.dll,oracle的使用和OracleClient完全一样,在程序中添加DLL引用就可以使用:

            using (OracleConnection conn = new OracleConnection(WebConfigurationManager.ConnectionStrings["oracleODP"].ConnectionString))
            {
                using (OracleCommand cmd = conn.CreateCommand())
                {
                    cmd.CommandText = "select username, tel from demobs.test where username = '" + TextBox1.Text + "'";
                    conn.Open();
                    OracleDataReader reader = cmd.ExecuteReader();
                    if (reader.Read())
                    {
                        TextBox1.Text = reader.GetString(1);
                    }
                }
            }

上面一段代码,无论你使用OracleDataAccess.dll还是OracleClient.dll她都能正常工作,唯一不同可能是连接字符串的一点点区别了。

继续阅读

很久都没写BLGO了,关于多态的第3篇文章一晃就1年了才写。有时比较迷茫,感觉太多东西都要学,什么都想学,却找不清方向了。呵呵,看着好多牛人的BLOG觉得自己水平实在是太差了。呵呵。有时甚至觉得自己写的东西太低级了。呵呵,或许是自己抱怨太多了,还是静下心来慢慢学习吧。以后一定多写一些东西,自己经常看看还是挺有帮助的。

如果大家对多态的机制还不了解,可以先查看上面这2篇文章。本篇本打算使用一些例子说话,但是实际大家明白了方法表的布局结构。其实是根本不需要任何实例去讲解了。所以这一篇主要算是查缺补漏吧。

 

 

一 多态的例子

 

class Program
    {
        static void Main(string[] args)
        {
            Cpu c1 = new Cpu();
            c1.fun();
            Cpu c2 = new IntelCpu();
            c2.fun();
            Cpu c3_1 = new NewCpu();
            c3_1.fun();
            NewCpu c3_2 = new NewCpu();
            c3_2.fun();
            Console.ReadKey();
        }
    }
    class Cpu
    {
        public virtual void fun()
        {
            Console.WriteLine("This is Cpu");
        }
    }
    class IntelCpu : Cpu
    {
        public override void fun()
        {
            Console.WriteLine("This is IntelCpu");
        }
    }
    class NewCpu : Cpu
    {
        public new void fun()
        {
            Console.WriteLine("This is NewCpu");
        }
    }

这个例子,主要是为了解释上一篇中遗留的new关键字时候的问题。我们主要从两个方面来讲解这个列子:

继续阅读

说到源码管理,CVS,VSS,SVN,TFS大家在公司可能都用的比较多了。但是在公司的环境基本都是在局域网中或者是专线连结到远程服务器来使用。平时自己在家和朋友一些写一些代码的时候都苦于没有代码管理工具,没有网络环境,而不能不把代码传来传去,很是麻烦。不过Google code提供了免费的SVN空间,主要注册了GMAIL,然后就可以使用SVN进行源码管理,和其他人共同开发了。网上有介绍的,不过我看了都不怎么详细,自己摸索了下,写下来大家分享下。

 

 

一 访问Google code

 

Google code的地址是 http://code.google.com/  ,如果使用cn去访问好像访问不了,我这里是一片空白。管理项目的话可以直接使用http://code.google.com/hosting/ 地址访问。用Gmail登录进去,页面的中间有【Create a new project 】,点击以后就可以创建项目了。

 

 

二 创建自己的项目

 

在创建项目的页面,填写项目名,概要和描述,其中项目名开头要小写,还不能有空格和其他符号。然后就是选择版本管理系统,证书等等,这些我也不懂,随便选吧,反正这有选好了,【Create Project】才可用。这里要注意的是项目名字可能冲突。如果创建成功就可以进入项目管理界面

三 项目管理

 

项目管理中,上方的菜单【Project Home】可以看到项目的概述和描述。点击【Source】就可以进行源码的管理。其中有2个地址,一个是Https开头的,一个是http的,https开头的是带加密的,所以如果要commit新的代码的时候就需要使用这个地址。而如果仅仅是取得代码可以只使用http开头的地址。

使用https的地址的时候需要提供用户名和密码,这里的用户名是Gmail的用户名,而密码是Google给每个项目生成的,而非是Gmail的密码。点击【When prompted, enter your generated googlecode.com password 】后面的蓝色连接可以看到密码。这个密码是你所有项目的密码,而不是每个项目一个密码。

四 用户管理

 

项目建立好以后就可以把其他人加入到项目中,这样就可以共同开发了。首先点击上方的【Administer】,然后点【Project members】,在下面填入要加入的用户Gmail就可以了。有Project owners,Project committers,Project contributors。具体解释右侧都有。点击保存后,其他用户登录后,在右上方的【My Favorite】下就可以看到自己加入的项目了。然后按三中介绍的方法找到密码。

 

 

五 其他管理

 

Google Code还提供了wiki等功能,我没用上,所以不是太了解。

 

 

六 安装客户端和VS插件

 

上面的工作做好后就是上传源码和文档。但是我找了半天也不知道怎么上传。以为是直接网页上上传,原来也要安装SVN客户端。在这里

http://tortoisesvn.net/downloads  可以下载到最新的TortoiseSVN,这个应该是目前用的最多的SVN客户端软件了。E文不好的朋友上面还提供了中文语言包。

安装完客户端后需要重启电脑,然后就可以远程连接到SVN服务器了。其中URL就填写Google 提供的哪个https的URL地址,然后填写用户名(Gmail)和密码(项目密码),保存后就OK了。客户端可以支持连接多个URL,每次启动的时候可以选择要连接到那一个。

 

支持SVN的VS插件我使用的是AnkhSvn,http://ankhsvn.open.collab.net/servlets/ProjectDocumentList?folderID=198 这里可以下载到最新版本。目前可以支持到VS2010,之前使用老版本对VS2008支持不好,文件状态不对,而且不能提交,换到最新版的时候就好了。安装的时候配置VS要比较长时间,不要以为是死掉了。如果只安装AnkhSvn而不安装TortoiseSVN也是可以的,不过你在VS中会发现,操作的功能少了很多,比如分支,合并等等。

 

七 使用VS进行开发和源码管理

 

进入到VS中,打开【工具】–【选项】–【Source Control】,默认应该是已经配置好了为AnkhSvn。然后可以点击【文件】-【Subvwrsion】打开服务器上的源码。和其他工具一样,要选择一个本地路径来保存。

 

1:文件状态介绍

蓝色小勾:Check out状态;橙色小勾:文件被修改状态;橙色小方块:文件修改被保存;加号:新添加文件。

 

2:SNV版本控制

和VSS不同的时,VSS默认是锁住的状态,需要手动Check Out,而SVN是自动Check Out。那么这样不是会有冲突吗,其实这个和VSS允许多人牵出是一样的。在你Commit的时候,会检查版本,会自动合并或提示冲突或是版本过期等等。

  • 获取最新代码:这个不用说了就是从服务器上拿最新代码,但是如果你修改了文件,然后拉最新代码,这个时候系统会自动吧你修改的不部分和最新代码进行合并,如果有冲突会提示,要修修改冲突。
  • 获取指定版本代码:这个可以通过查看历史,或者指定版本号来拉去指定版本的代码。这是同样会合并代码。需要注意的是,SVN的版本号和VSS不同,是全局版本号,而不是每个文件有一个版本号。这个要特别注意,因为你会发现一个文件版本号可能是跳跃的。
  • Switch:有这样一个功能,可以把当前版本切换为制定的版本,和获取指定版本不同,他也会自动合并不同的地方。
  • Revert:恢复功能,恢复到修改前的状态。这个要注意的是,如果你对文件修改,然后获取了最新代码,然后恢复,这个时候是恢复到最新版本,而不是修改前的那个版本。这点要注意
  • 版本冲突:这里版本冲突有2种情况,如果你当前版本为1,服务器版本为2,你修改或提交,服务器会提示你本地版本过期了,你可以拉最新代码,并解决冲突后再次提交;如果你当前版本为2,服务器版本为2,而你从服务器获取版本1的代码,修改后,然后提交,这个时候是不会提示版本过期的,会覆盖掉服务器上的版本2,而成为版本3。这样是会冲掉代码的。
  • 锁:SVN提供了锁的功能,就和VSS的单用户Check out是一样的,不能同时修改。但是目前Google Svn不提供锁的功能,所以没有办法使用了。

 

 

八 SVN资料

 

以前没有使用过SVN的源码管理,所以有些地方感觉不一样。关于SVN的版本控制的方法和SVN介绍可以参考一下网站

http://www.subversion.org.cn/svnbook/1.4/svn.basic.vsn-models.html

 一 流的概念

 

在.NET中Stream 是所有流的抽象基类。流是字节序列的抽象概念,或者说是计算机在处理文件或数据时产生的二进制序列。例如文件、输入/输出设备、内部进程通信管道或者 TCP/IP 套接字。Stream 类及其派生类提供这些不同类型的输入和输出的一般视图,使程序员不必了解操作系统和基础设备的具体细节。简单的说流提供了不同介质之间的数据交互功能。

在.NET中常用的流有BufferedStream 、FileStream、MemoryStream和NetworkStream,他们都是位于System.IO和System.Net命名空间下。流涉及三个基本操作: 读取,写入和查找。根据基础数据源或储存库,流可能只支持这些功能中的一部分。有些流实现执行基础数据的本地缓冲以提高性能。对于这样的流,Flush 方法可用于清除所有内部缓冲区并确保将所有数据写入基础数据源或储存库。

 

 

继续阅读

最近正好做一个WEB中定期执行的程序,而.NET中有3个不同的定时器。所以正好研究研究。这3个定时器分别是:

//1.实现按用户定义的时间间隔引发事件的计时器。此计时器最宜用于 Windows 窗体应用程序中,并且必须在窗口中使用。
System.Windows.Forms.Timer

// 2.提供以指定的时间间隔执行方法的机制。无法继承此类。
System.Threading.Timer

//3.在应用程序中生成定期事件。
System.Timers.Timer

这三个定时器位于不同的命名空间内,上面大概介绍了3个定时器的用途,其中第一个是只能在Windows窗体中使用的控件。在.NET1.1里面,第3个System.Timers.Timer,也是可以拖拽使用,而.NET2.0开始取消了,只能手动编写代码。而后2个没有限制制。下面通过具体的列子来看3个Timer的使用和区别,网上谈的很多,但基本都没有代码。

System.Windows.Forms.Timer

 

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        int num = 0;
        
        private void Form_Timer_Tick(object sender, EventArgs e)
        {
            label1.Text = (++num).ToString();
            Thread.Sleep(3000);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Form_Timer.Start();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            Form_Timer.Stop();
        }
    }

继续阅读

最近在看垃圾回收的IDispose的接口实现,平时经常听到某个类型要执行什么操作需要实现什么接口,某个类型实现了什么接口。但我们用的系统提供的类型都已经实现了这些接口,但到底怎么实现的我们不清楚。所以我们就把这些常用的接口实现在自己的类型中。让他们具有一定功能,也让我认识下这些接口。

下面的例子中一共实现了IComparable,IComparer,IEnumerable,IEnumerator和IDisposable,实现这些接口,我们的类型就可以在List或Array中进行排序,使用foreach进行遍历,手动释放资源或使用using块。在看代码前先说明下,2.0中增加了泛型的支持,所以也有了泛型的接口。我下面说的主要是针对接口,而不管是不是泛型(区别不大),但代码中都是实现的泛型接口。所以看到介绍是非泛型,代码是泛型不要误会,我主要是介绍接口以及实现。

 

 

一 实现IComparable,IComparer接口

 

  • IComparable:定义由值类型或类实现的通用的比较方法,以为排序实例创建类型特定的比较方法。
  • IComparer:定义类型为比较两个对象而实现的方法。

通常我们要在数组或链表中对一个对象进行排序,这就需要对对象进行比较。但因为数组和链表可以存放各种数据,值类型,引用类型,或是我们自建类型,所以它不可能去实现各个类型的比较方法,而需要类型自己实现。所以,.NET中如果一个类型实现了IComparable接口,那么他就可以被排序,因为排序算法知道去调用这个类型的CompareTo方法。但是有时候我们类型有多个字段,需要能选择的进行排序,这个时候就需要在此类型中实现IComparer接口,以便按自己的方式进行排序。如果不实现此接口,系统会自己产生一个默认的实现。但是要注意的是2个接口的实现不是直接在一个类上,而是通过嵌套类。

继续阅读

在前一篇深入了解.NET中继承和多态(上) 中我们已经知道了对象在内存中的布局结构,这一篇我们讲主要研究继承和多态。主要是通过列子来看问题。其中会涉及到使用SOS进行扩展调试和查看IL代码。

 

一 调用方法的IL指令

 

 

我们知道在.NET中一共有三种方法:实例方法,静态方法和虚方法。当程序被编译成IL代码时,我们可以看到有两个调用方法的IL指令,分别是callcallvirt我们首先看下下面的列子:

    class Cpu
    {   
        public Cpu()
        {
            Console.WriteLine("初始化Cpu");
        }
        public void fun()
        {
            Console.WriteLine("Cpu的方法/n");
        }
        public static void fun2(){ }
        
        public virtual void fun3(){ }
        
        public override string ToString()
        {
            return base.ToString();
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Cpu c1 = new Cpu();
            c1.fun();           //调用实例方法 
            Cpu.fun2();       //调用静态方法 
            c1.fun3();          //调用虚方法 
            c1.ToString();     //调用重写基类的虚方法 
        }
    }

以下是Main方法的IL代码

继续阅读

注意:在写完文章后很久才发现自己文章中【编译】两个字的让人误解,比如方法槽偏移量是在编译时获得的,其实我想表达的是JIT编译,而不是指IL编译。我大概修改了一些关键地方,但是可能有很多遗漏。大家要自己判断了,哈!

封装、继承、多态是面向对象的最重要的3个特点。但是想真的弄明白他们其中的奥秘还是的费一番功夫。记得在学校学习C++的时候,讲到这个地方,自己早已是一头雾水,当时还在想,弄成private做什么,多麻烦啊。到了多态,继承更是昏死了。今天就来深入了解下其中的奥秘吧。本文主要是从内存结构出发来讲解.NET中的继承和多态,因为内存布局的不同所以和其他语言中的继承多态可能有一定区别。

 

 

一 笔试题目

 

 class Program
    {
        static void Main(string[] args)
        {
            Cpu c1 = new Cpu();
            c1.fun();
            Cpu c2 = new IntelCpu();
            c2.fun();
            Cpu c3 = new CoreCpu();
            c3.fun();
            IntelCpu  c4 = new CoreCpu();
            c4.fun();
        }
    }
    class Cpu
    {   
        public Cpu()
        {
            Console.WriteLine("初始化Cpu");
        }
        public virtual void fun()
        {
            Console.WriteLine("Cpu的方法/n");
        }
    }
    class IntelCpu : Cpu
    {
        public IntelCpu()
        {
            Console.WriteLine("初始化IntelCpu");
        }
        public override void fun()
        {
            Console.WriteLine("IntelCpu的方法/n");
        }
    }
    class CoreCpu : IntelCpu
    {
        public CoreCpu()
        {
            Console.WriteLine("初始化CoreCpu");
        }
        public new void fun()
        {
            Console.WriteLine("CoreCpu的方法/n");
        }
    }

上面是我们常见的关于继承和多态的题目。或许很多人都有一套做这种题目的方法,能够让你准确的得到答案,但是我们了解继承和多态不是为了背公式,不是为了做题目,是未来灵活使用。所以有必要弄清楚她内部到底是怎么实现的。或许平时可能用不上,但是我认为还是会有所帮助的。

继续阅读

前端时间在一个.NET和C通信的接口测试中发现一个问题,由.NET发送到C的中文字显示是问号。应该是编 码的问题,但是具体是什么原因呢?自己不太清楚,然后找了一些相关资料看了下,总算对字符和编码有了 一定了解。

 

 

一 简单的程序

 

string msg = "欢 迎访问cc_net";
int l1 = System.Text.Encoding.Default.GetByteCount (msg);
int l2 = System.Text.Encoding.ASCII.GetByteCount (msg);
int l3 = System.Text.Encoding.Unicode.GetByteCount (msg);
int l4 = System.Text.Encoding.UTF8.GetByteCount (msg);
int l5 = System.Text.Encoding.BigEndianUnicode.GetByt eCount(msg);
int l6 = System.Text.Encoding.UTF32.GetByteCount (msg);
int l7 = msg.Length;

以上是一段计算字符串长度的信息 。你能准确说出他们的值吗?? 下面是他们的实际结果

 

继续阅读