一年又端午,

且斟酒在壶。

遥想离骚愤,

歌罢人已无。

漫漫多歧路,

求索常坎途。

诸君当珍重,

举杯同祝福。

posted @ 2008-06-07 12:34 炭炭 阅读(25) | 评论 (1)编辑
     青春是一团
  夜风中颤动的篝火
  可我一点点
  也不愿对夜妥协
  
  青春是一团
  不能添材的篝火
  可我一点点
  也不愿有所保留
  
  不要和我讲
  星星的永恒
  在那一刻
  星空下征服你的眼
  
  不要在黎明
  寻找我的痕迹
  唯一留下的
  是你对温暖的记忆
posted @ 2008-06-03 20:23 炭炭 阅读(18) | 评论 (0)编辑


1 将所有静态变量设置为0
2 执行静态变量初始化器
3 执行基类的静态构造器
4 执行当前类型的静态构造器
5 将所有的实例变量设置为0
6 执行实例变量初始化器
7 执行合适的基类实例构造器
8 执行当前类型的实例构造器

构造相同类型的后续实例,其步骤将从第5步开始,即静态的不需要重新构造。初始化器就是赋值语句。
posted @ 2008-05-30 13:25 炭炭 阅读(27) | 评论 (0)编辑
     摘要: 事件是委托的特殊形式。特殊在什么地方呢:事件必须多播。多播必须使用+=而不能用=加载。事件本身是 Observer 模式“推”模型的标准表现形式。第一个参数object Sender是事件的监测对象,用“this ”的话就是触发事件的类,可以使"观察者"访问到触发事件的类的内部成员变量。第二个参数EventArgs是你要推给"观察者"的数据,当然你要... 阅读全文
posted @ 2008-05-20 21:40 炭炭 阅读(29) | 评论 (0)编辑

先说区别,原文出处 http://www.dotnetspider.com/resources/740-Difference-between-class-struct-C.aspx
1,class 是引用类型,structs是值类型
既然class是引用类型,class可以设为null。但是我们不能将struct设为null,因为它是值类型。

    
struct AStruct
{
   
int aField;
}
class  AClass
{
   
int aField;
}
class MainClass
{
public static void Main()
{
AClass b 
= null// No error.
AStruct s = null// Error [ Cannot convert null to 'AStruct' 

because it 
is a value type ].
}
}

2,当你实例一个class,它将创建在堆上。而你实例一个struct,它将创建在栈上

3,你使用的是一个对class实例的引用。而你使用的不是对一个struct的引用。(而是直接使用它们)

4,当我们将class作为参数传给一个方法,我们传递的是一个引用。struct传递的是值而非引用。

5,structs 不可以有初始化器,class可以有初始化器。

class MyClass
{   
 
int myVar =10;  //  no syntax error.    public void MyFun( ) 
   {       //  statements    }
}
struct MyStruct
{    
int myVar = 10;  //  syntax error.   
 public void MyFun( )  
  {       
//  statements    }
}


6
Classes 可以有明显的无参数构造器,但是Struct不可以

class MyClass
{   
  
int myVar = 10
  
public MyClass( ) // no syntax error.  
 {    
// statements
 }
}
struct MyStruct
{  
  
int myVar; 
  
public MyStruct( ) // syntax error.
   {       
  
// statements  
   }
}

7 类使用前必须new关键字实例化,Struct不需要

MyClass aClassObj;     //  MyClass aClassObj=new MyClass(); is the correct format.aClassObj.
myVar=100;//NullReferenceException(because aClassObj does not contain a reference to an object of type myClass).    
MyStruct  aStructObj;
aStructObj.myVar
=100//  no exception.

8 class支持继承和多态,Struct不支持. 注意:但是Struct 可以鹤类一样实现接口
9 既然Struct不支持继承,其成员不能以protected 或Protected Internal 修饰
10 Class的构造器不需要初始化全部字段,Struct的构造器必须初始化所有字段
class MyClass    //No error( No matter whether the Field ' MyClass.myString ' is initialized or not ). 

 
int myInt;  
 
string myString;   
 
public MyClass( int aInt )
      {    myInt 
= aInt;    }
}
struct MyStruct    // Error ( Field ' MyStruct.myString ' must be fully assigned before it leaves the constructor ).

  
int myInt;  
  
string myString; 
  
public MyStruct( int aInt ) 
   {    
    myInt 
= aInt;  
   }
}
11 Class可以定义析构器但是Struct不可以
12 Class比较适合大的和复杂的数据,Struct适用于作为经常使用的一些数据组合成的新类型。

适用场合:Struct有性能优势,Class有面向对象的扩展优势。
用于底层数据存储的类型设计为Struct类型,将用于定义应用程序行为的类型设计为Class。如果对类型将来的应用情况不能确定,应该使用Class。
posted @ 2008-05-18 18:14 炭炭 阅读(89) | 评论 (0)编辑

最近看了园子里的面向对象与过程之争,忍不住想说两句,因为我感觉这里面对OO存在一些关键误解,不说出来真的是难受。我有什么说错的地方,也欢迎大家指出。

首先,题目引用的是《人月神话》中的典故,面向对象是在软件危机的大背景下产生的,被作者称为“铜弹”,相对于作者理想中的至今仍未出现的“银弹”来说,我觉得已经是一种赞誉了。

开发,说到底就是人与机器的对话。这里面我们以前忽略了一个平衡问题。软件危机的本质,我觉得就是我们的思维太偏向于机器而忽略了人这一要素。我们用面向过程的方式组织程序就是从CPU的角度出发,一切都是按顺序执行,按顺序组织。刚开始程序简单没什么。可是随着系统的越来越复杂,人这一要素在人与机器的对话过程中“崩溃”了,因为在面对成千上万的函数过程时,人脑接受不了了,人脑不是这么认识事物的!而最重要的是,需求不可能不变的,我们没有封装变化点,那么每一个变化都会有牵一发而动全身的效果。什么意思,你改变了一处代码,你的功能正常了,其他的地方崩溃了,于是你再改,再崩溃,再修改.....记得《人月神话》里那个在“焦油坑”挣扎的怪兽吗,越挣扎陷的越深,多么形象啊。

面向对象的出现,它的伟大之处就在于在机器与人之间找到新的平衡点。从人的角度而不再是CPU的角度来组织程序。小余说的“软件学的本质来说,面向对象并没有改变软件运行的本质,所改变的只是代码开发中问题处理和思维方式 ”是多么正确啊。但是不要小看它阿,正是这一点点改变,才是它的伟大之处。不再忽略开发中人的要素,才使我们构建更复杂的系统成为可能!如果没有OO,我无法想象现在会有如此多的优秀的软件产品。

究竟OO给我们带来了什么? 什么封装、多态,继承什么的我就不想多说了,比我理解的透的高人多了去了。我就说一下面向对象的核心原则:OCP。开发封闭原则,什么意思? 一言以蔽之:我们编写的程序,要能扩展,而且扩展的同时不需要改变已有的代码,上层逻辑的代码不需要根据具体实现的不同而改变。于是我们不再被变化拖入“焦油坑”,其意义真的不亚于一场革命!

现在的语言都是OO的了,什么C#,Java。但是现实的问题不是我们强调的面向对象不是太多,而是太少。用的OO语言干的面向过程的勾当这种事实在是太多太多了。你用了C#但你的程序可能和OCP边都沾不上。很多项目OO语言下其实就是一堆面向过程的程序,当初写代码的人一走,复用,维护,扩展都几乎是不可能的,很多项目的失败就是这个简单的原因。相反,我从来没看到过因为“过分”强调OO而导致项目失败的事。

当然我也细想了一下为什么有时候OO会被人诟病。我想这与我们对OO的一个误解有关:OO就是现实对象的隐射,实现OO就是要“道法自然”“一切皆对象”。这是误解也是很可笑的,如前所述OO是“代码开发中问题处理和思维方式”,根据解决问题的不同,甚至封装的变化点不同,最终得到的OO设计是不尽相同的。肯定不是现实中有什么你就要设计什么对象,更不能以现实对象的行为作为构建对象的依据。把问题简单化,忽略了这中间有个重要的抽象过程,难怪会被人抓住小辫子。比如我记得book.save()到底够不够OO的争论,在我看来这与现实中book能不能save自己是一点关系没有的,至于说够不够OO要你解决的上下文看。

至于对象设计的原则我推荐大家看《.net 设计规范》,其实这本书正确的翻译是《.net 框架设计规范》,讲的是微软的大牛们怎么设计.net框架里的对象的。其中的重要一点原则就是站在对象使用者最常用的使用场景下设计对象,简单说就是站在程序员的角度,看你们习惯怎么用,人家就怎么设计,这与敏捷开发中的测试驱动是异曲同工的。所以说OO的对象设计成什么样,到底这个设计够不够OO,都是由应用这个对象的人和应用场景决定的。

也许有人说我说了一堆废话,希望是这样。

posted @ 2008-05-12 22:09 炭炭 阅读(1126) | 评论 (10)编辑

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.IO;

public partial class _Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
    }
    protected void btnLogin_Click(object sender, EventArgs e)
    {
        DataSet ds = new DataSet();
        FileStream fs = new FileStream(Server.MapPath("LoginMsg.xml"), FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
        StreamReader reader = new StreamReader(fs);
        ds.ReadXml(reader);
        fs.Close();

        DataTable dt = ds.Tables[0];
        DataRow dr = dt.NewRow();
        dr["custom_email"] = this.TextBox1.Text;
        dr["custom_pass"] = this.TextBox2.Text;
        dr["login_time"] = DateTime.Now.ToString();

        fs = new FileStream(Server.MapPath("LoginMsg.xml"), FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
        TextWriter writer = new StreamWriter(fs);
        writer = TextWriter.Synchronized(writer);
        ds.Tables[0].Rows.Add(dr);
        ds.WriteXml(writer);
        writer.Close();
        Cache.Remove("myData");
        LoadData();
       
    }

    public void LoadData()
    {
        DataView source = (DataView)Cache["myData"];
        if (source == null)
        {
            DataSet ds = new DataSet();
            FileStream fs = new FileStream(Server.MapPath("LoginMsg.xml"), FileMode.Open, FileAccess.Read);
            StreamReader reader = new StreamReader(fs);
            ds.ReadXml(reader);
            fs.Close();
            source = new DataView(ds.Tables[0]);
            Cache.Insert("myData", source, new System.Web.Caching.CacheDependency(Server.MapPath("LoginMsg.xml")));
            this.Label1.Text = "read from file";
        }
        else
        {
            this.Label1.Text = "read form cache";
        }
        this.GridView1.DataSource = source;
        this.GridView1.DataBind();
   
    }
    protected void btnRefresh_Click(object sender, EventArgs e)
    {
        LoadData();
    }
}

posted @ 2008-05-11 15:41 炭炭 阅读(24) | 评论 (0)编辑

不必借助监控程序(例如WIndows的性能计数器或SQL Server Profiler),SqlConnection也能获取T SQL的执行状态,结果可用于性能分析。

程序片断如下:
......
   sConn.StatisticsEnabled = true;
    
if (!string.IsNullOrEmpty(iSQL))
            {
               using (SqlCommand iCmd=new SqlCommand (iSQL,sConn ))
               {
                  iCmd .ExecuteNonQuery ();
               }           
            }
   
  IDictionaryEnumerator iEnum =sConn.RetrieveStatistics().GetEnumerator ();
......
默认情况下,SQlConnection不提供统计信息,要使用此功能需要将StatisticsEnabled 设为true. SqlConnection的 RetrieveStatistics 方法返回在调用该方法时统计数据的键值对集合,可以如代码所示获取其信息察看。
posted @ 2008-05-10 22:07 炭炭 阅读(21) | 评论 (0)编辑


当执行某些需要花费很长时间才能完成的数据库操作时,往往需要设置设计异步的处理的方法,以避免用户长期得不到响应,导致程序假死。在ADO.Net 2.0中,其SqlCommand类也提供了一组Begin~和End~的Execute方法对,用于执行异步操作,通过这些方法对,用户可以轻松地实现异步操作,而不需要掌握过多的线程开发技术细节。比如ExecuteNonQuery 相应的异步方法为 BeginExecuteNonQuery,EndExecuteNonQuery。

同步与异步方法在调用上的差异在于:同步方法执行后,会阻塞处理进程,直接返回处理结果,而异步执行方法通过Begin~方法启动执行处理,然后将处理权交给调用者,调用者可以做别的事情,如果要取得异步执行的结果,需要调用End~方法,否则结果会丢失。

在异步执行处理中,主要需要考虑的是在异步执行开始后(通过Begin~方法的调用),如果获取异步执行的状态,以便在需要的时候,通过End~方法取回异步执行的结果。每个IAsyncResult接口对象,如果需要知道Begin~方法执行的状态,可以查询IAsyncResult接口对象的IsCompleted属性。当该属性返回True时,表示异步方法执行完成,可以调用与之对应的End~方法获取执行结果。 如果在异步执行完成前调用~End方法,则~End方法会等待,阻塞主线程,直到异步方法执行完成并返回结果。比较常用的另一种方法是:在调用Begin~方法开始异步执行时,传入委托实例。Begin~有几个重载,其中有2个可以传入委托实例,由执行异步方法的工作线程通过委托自动回调制定的回调函数。下面这个例子说明了这种方法。



如图建立Windows程序,下方是一TabPage控件。代码如下

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Data.SqlClient;

namespace queryCallBackDemo
{
    public partial class Form1 : Form
    {
        private Int32 m_runningCount = 0;
        private string m_ConnStr = "Data Source=xiaoxiao\\SQLEXPRESS;Initial Catalog=tempdb;Integrated Security=True;Asynchronous Processing=true";
        private SqlConnection getConnection()
        {
            SqlConnection iRe = new SqlConnection(this.m_ConnStr);
            iRe.Open();
            return iRe;
        }


        private delegate void addNewTabPageDelegate(TabPage sTabPage);

        private void addNewTabPage(TabPage sTabPage)
        {
            this.tabControl1.TabPages.Add(sTabPage);

        }

        private void handleCallBack(IAsyncResult iResult)
        {
            try
            {
                using (SqlCommand iCmd = iResult.AsyncState as SqlCommand)
                {
                    TabPage iTabPage = new TabPage(iCmd.CommandText);
                    DataGridView iDataGridView = new DataGridView();
                    iDataGridView.Parent = iTabPage;
                    iDataGridView.Dock = DockStyle.Fill;
                    using (DataTable iDatatable = new DataTable())
                    {
                        iDatatable.Load(iCmd.EndExecuteReader(iResult));
                        iDataGridView.DataSource = iDatatable;

                    }
                    this.Invoke(new addNewTabPageDelegate(this.addNewTabPage), iTabPage);

                  //  this.tabControl1.TabPages.Add(iTabPage);
                }

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            finally
            {
                this.m_runningCount -= 1;
            }

        }


        private void asyncExecuteQuery(string sSQL)
        {
            SqlCommand iCmd;
            try
            {
                iCmd = new SqlCommand(sSQL, getConnection());
                iCmd.BeginExecuteReader(new AsyncCallback(this.handleCallBack), iCmd);
                this.m_runningCount += 1;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }

        }


        public Form1()
        {
            InitializeComponent();
        }


        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (this.m_runningCount > 0)
            {
                MessageBox.Show(m_runningCount.ToString() + "  query are still running, please wait");
                e.Cancel = true;
            }
        }

        private void btnDoquery_Click(object sender, EventArgs e)
        {
            string iSQL = this.textBox1.Text.Trim();
            if (!string.IsNullOrEmpty(iSQL))
                this.asyncExecuteQuery(iSQL);
        }

        private void btnClear_Click(object sender, EventArgs e)
        {
            if (this.m_runningCount > 0)
                MessageBox.Show(m_runningCount.ToString() + "  query are still running, please wait");
            else
                this.tabControl1.TabPages.Clear();
        }
    }
}


几个注意:连接串加上 Asynchronous Processing=true 。

iCmd.BeginExecuteReader(new AsyncCallback(this.handleCallBack), iCmd);  开始异步委托调用,
SqlCommand iCmd = iResult.AsyncState as SqlCommand 获取传入的ICmd

异步调用中不能直接   this.tabControl1.TabPages.Add(iTabPage);
因为tabControl1.是在另一个线程中创建的,而要使用  this.Invoke(new addNewTabPageDelegate(this.addNewTabPage), iTabPage);

 

 

posted @ 2008-05-09 17:07 炭炭 阅读(72) | 评论 (0)编辑

SqlBulkCopy 类就像名字所描述的一样是专门用于批量复制的。相对于其他将数据加载到SQL Server表中的方式,使用SqlBulCopy具有明显的性能优势。这个类只能用于向SQL Server表中写入数据。但是,可以使用任何数据源,主要数据可以加载到DataTable或使用DataReader实例读取即可。

下面是一个演示的例子,关于SqlBulkCopy注意NotifyAfter属性的含义, 这个属性设定的是Copy多少行后触发SqlRowsCopied  事件,事件的加载就不多说了。

这个例子
同样使用了专门处理分布式事务的TransactionScope的类,TransactionScope是ADO.net 2.0中提供了一个轻量级的事务容器,可以允许我们方便的创建分布式事务, 用户根本不需要考虑是简单事务还是分布式事务. TransactionScope会自动根据事务中涉及的对象资源判断使用何种事务管理器.。

以下例子来源于邹建的书,不过我用C#改写了。

using System;
using System.Collections.Generic;
using System.Text;
using System.Data.SqlClient;
using System.Transactions;
using System.Data;

namespace ConsoleApplication2
{
    
class Program
    
{
        
private static string m_ConnStr = "Data Source=tantan\\SQLEXPRESS;Initial Catalog=tempdb;Integrated Security=True";

        
public static void InitTest(SqlConnection sConn)
        
{
            
using (SqlCommand iCmd = new SqlCommand())
            
{
                iCmd.Connection 
= sConn;
                iCmd.CommandText 
= "SELECT TOP 0 * INTO dbo.tb_bulk_test_objects FROM sys.objects";
                iCmd.ExecuteNonQuery();

                iCmd.CommandText 
= "SELECT TOP 0 * INTO dbo.tb_bulk_test_columns FROM sys.columns";
                iCmd.ExecuteNonQuery();
            
            }

        }


        
private static void OnsqlRowsCopied(object sender, SqlRowsCopiedEventArgs args)
        
{
            Console.WriteLine(String.Format(
"Copied {0} so far.", args.RowsCopied.ToString()));       
        
        }

        
private static void Bulk(SqlConnection sConn, string sSourceSQL, string sDestinationTable)
        
{
            
using (SqlCommand iCmd = new SqlCommand(sSourceSQL,sConn))
            
{
                
using (SqlBulkCopy iBcp = new SqlBulkCopy(sConn))
                
{
                    iBcp.NotifyAfter 
= 1000;
                    iBcp.DestinationTableName 
= sDestinationTable;
                    iBcp.SqlRowsCopied 
+= OnsqlRowsCopied;
                    
using (DataTable iDataTable = new DataTable())
                    
{
                        iDataTable.Load(iCmd.ExecuteReader());
                        iBcp.WriteToServer(iDataTable);                    
                    }

                    iBcp.SqlRowsCopied 
-= OnsqlRowsCopied;
                }

            }

        }


        
public static void BulkTest()
        
{
            
using (TransactionScope iTs = new TransactionScope())
            

               
                
using (SqlConnection iConn=new SqlConnection (m_ConnStr))
                
{
                    iConn.Open();
                    InitTest(iConn);
                    DateTime iDate;
                    
string iSQL;
                    iDate 
= DateTime.Now;
                    Console .WriteLine (
string.Format ("{0} start 1 batch processing",iDate));
                    iSQL 
= "SELECT o.* FROM sys.objects o, sys.columns c";
                    Bulk(iConn, iSQL, 
"dbo.tb_bulk_test_objects");
                    Console.WriteLine(
string.Format("{0} finish 2 batch processing", iDate));
                    
                    iDate 
= DateTime.Now;
                    Console.WriteLine(
string.Format("{0} start 2 batch processing", iDate));
                    iSQL 
= "SELECT c.* FROM sys.objects o,sys.columns c";
                    Bulk(iConn, iSQL, 
"dbo.tb_bulk_test_columns");
                    Console.WriteLine(
string.Format("{0} finish 2 batch processing", iDate));
                
                }

                iTs.Dispose();
            
            }
       
        
        }

        
private 
        
static void Main(string[] args)
        
{

            BulkTest();
            Console.WriteLine(
"Done");
            Console.ReadKey(); 
        }

    }

}







 
posted @ 2008-05-08 16:35 炭炭 阅读(58) | 评论 (0)编辑