分享

CYQ.Data 轻量数据层之路 SQLHelper 回头太难(八)

 quasiceo 2016-07-06

提前说明:正如网友反映的一样,为了不至于产生明显的误导,特别加了此首段说明

SQLHelper,几乎是每个过来者必经的阶段,写好一个SQLHelper是非常重要的一环,所以希望年轻的来者,要多加实践,别只看不动手,哪怕照着写一写,也是相当的有益。

对于本框架系列,希望年轻来者在掌握使用的同时,动手照着系列文章写一写,如果照着写出来的,相信成长不是一点半点的;别光看不练,最后只能忽悠却动不了手。

 

 

 

这篇文章很不好写,我在电脑前思索了一天,也不知怎么下手。

关于SQLHelper的文章遍地都是,写的不咋的随时被拍砖,不写吧,本系列又不完整,所以,买了个保险之后,低调点写了。

 

从哪写起呢?直接把整个SQLHelper类复制一下,文章就算写完了?好像其它遍地都是的文章都差不多是这个样子的。

 

在还没写完这篇时,曾经有那么个热心人士反编绎过我的框架,还洒了点代码出来了,提前爆光了一下:

详见:

1:CYQ.Data 轻量数据层之路 华丽升级 V1.3出世(五)

2:CYQ.Data 轻量数据层之路 应用示例二 在线聊天(六)

 

本文停了一天没动了,现在重新执笔动手了,想了想,于是在博客园搜了一下,看了第一页搜出来的10篇SQLHelper相关代码,

简略看了一眼,发现还是鄙人的简洁友好的多,于是,继续写下来了:

 

其实我们要的SQLHelper很简单,只要能执行下sql语句和存储过程,也就这个样了,至于事务,这里先放一边了。

接着一步一脚印:

1:我们新增加一个SQHelper类,由于本类并不对外开放,所以我们不改修饰符为public,默认就好了

复制代码
    /// <summary>
    
/// SQLHelper by 路过秋天
    
/// </summary>
    class SQLHelper
    {

    }
复制代码

 

2:由于我们不做成静态方法调用方式,所以我们需要实例化,添加两个构造函数

复制代码
 /// <summary>
    
/// SQLHelper by 路过秋天
    
/// </summary>
    class SQLHelper
    {
        
/// <summary>
        
/// 默认配置连接字符串名:Conn
        
/// </summary>
        public SQLHelper()
        {
           
        }
        
/// <summary>
        
/// 可以传链接字符串
        
/// </summary>
        
 public SQLHelper(string conn)
        {
           
        }
    }
复制代码

 

3:既然要实例化才调用,那我们只需要一个Command和一个链接就可以了,所以,我们把它们拿到外面定义成全局变量

复制代码
    class SQLHelper
    {
        
private SqlCommand com = new SqlCommand();
        
private SqlConnection _con = null;
        
/// <summary>
        
/// 默认配置连接字符串名:Conn
        
/// </summary>
        public SQLHelper()
        {
           
        }
        
/// <summary>
        
/// 可以传链接字符串
        
/// </summary>
        public SQLHelper(string conn)
        {
           
        }
    }
复制代码

上面没有直接new 出SqlConnection,是因为它和链接字符串相关,留到构造函数里初始化了。

 

4:实现构造函数,初始化SqlConnection

复制代码
        public SQLHelper()
        {
            
if (ConfigurationManager.ConnectionStrings["Conn"!= null)
            {
                _con 
= new SqlConnection(ConfigurationManager.ConnectionStrings["Conn"].ConnectionString);
                com.Connection 
= _con;
            }
        }
        
public SQLHelper(string conn)
        {
            
if (conn.Length < 25)
            {
                conn 
= ConfigurationManager.ConnectionStrings[conn].ConnectionString;
            }
            _con 
= new SqlConnection(conn);
            com.Connection 
= _con;
        }
复制代码

 默认用webconfig配置Conn,同时上面根据传入的长度,来判断是从配置文件传入,还是直接的链接字符串!

 

5:我们增加一个全局的成员属性,一个是否记录异常,如果不记录则会抛出异常

public bool WriteLog = true;

 

6:我这里另开一个Log类,来处理异常,先留下一个静态空方法,回头处理

复制代码
class Log
{
        
public static void WriteLog(string message)
        {
             
//...待实现...
        }
}
复制代码

 

7:要执行SQL语句或存储过程,免不了要打开和关闭链接,这里封装成方法,加try

复制代码
        private void OpenCon()
        {
            
try
            {
                
if (_con.State == ConnectionState.Closed)
                {
                    _con.Open();
                }
            }
            
catch (SqlException err)
            {
                
if (WriteLog)
                {
                    Log.WriteLog(err.Message);
                }
            }

        }
        
private void CloseCon()
        {
            
try
            {
                
if (_con.State == ConnectionState.Open)
                {
                    _con.Close();
                }
            }
            
catch (SqlException err)
            {
                
if (WriteLog)
                {
                    Log.WriteLog(err.Message);
                }
            }
        }
复制代码

我们在打开和关闭异时,调用了日志记录功能。

 

8:我们继承IDisposable接口,完成资源释放

复制代码
class SQLHelper:IDisposable
{
        
//...省略N行...

        
#region IDisposable 成员

         
public void Dispose()
        {
            
if (_con != null)
            {
                CloseCon();
                _con 
= null;
            }
            
if (com != null)
            {
                com 
= null;
            }
        }

        
#endregion
}
复制代码

 

 

9:我们封装一下SqlCommand的几个执行返回

复制代码
        internal int ExeNonQuery(string procName, bool isProc)
        {
            
//更新删除操作,返回受影响行数
         }
        
internal object ExeScalar(string procName, bool isProc)
        {
            
//返回首行首列的单个记录
         }
        
internal SqlDataReader ExeDataReader(string procName, bool isProc)
        {
            
//返回读取流
         }
        
internal DataTable ExeDataTable(string procName, bool isProc)
        {
            
//返回DataTable,本框架没用到,因为有了MDataTable
        }
复制代码

 

由于存储过程和单独的sql语句混在一起,我加了一个函数来处理这些共同的事情:

复制代码
        private void SetCommandText(string commandText, bool isProc)
        {
            com.CommandText 
= commandText;
            com.CommandType 
= isProc  CommandType.StoredProcedure : CommandType.Text;
            
if (!com.Parameters.Contains("ReturnValue"))
            {
                com.Parameters.Add(
"ReturnValue", SqlDbType.Int).Direction = ParameterDirection.ReturnValue;
            }
        }
复制代码

后面附加了一个常用的返回值参数ReturnValue。

 

10:实现封装的几个方法,异常则记录日志/抛出

复制代码
        internal int ExeNonQuery(string procName, bool isProc)
        {
            
//更新删除操作,返回受影响行数
            SetCommandText(procName, isProc);
            
int rowCount = 1;
            
try
            {
                OpenCon();
                com.ExecuteNonQuery();
            }
            
catch (SqlException err)
            {
                rowCount 
= 0;
                
if (WriteLog)
                {
                    Log.WriteLog(err.Message);
                }
            }
            
return rowCount;
        }
        
internal object ExeScalar(string procName, bool isProc)
        {
            
//返回首行首列的单个记录
            SetCommandText(procName, isProc);
            
object returnValue = null;
            
try
            {
                OpenCon();
                returnValue 
= com.ExecuteScalar();
            }
            
catch (SqlException err)
            {
                
if (WriteLog)
                {
                    Log.WriteLog(err.Message);
                }
            }
            
return returnValue;
        }
        
internal SqlDataReader ExeDataReader(string procName, bool isProc)
        {
            
//返回读取流
            SetCommandText(procName, isProc);
            SqlDataReader sdr 
= null;
            
try
            {
                OpenCon();
                sdr 
= com.ExecuteReader(CommandBehavior.CloseConnection);
                
if (sdr != null && !sdr.HasRows)
                {
                    sdr.Close();
                    sdr 
= null;
                }

            }
            
catch (SqlException err)
            {
                
if (WriteLog)
                {
                    Log.WriteLog(err.Message);
                }
            }
            
return sdr;
        }
        
internal DataTable ExeDataTable(string procName, bool isProc)
        {
            
//返回DataTable,本框架没用到,因为有了MDataTable
            SetCommandText(procName, isProc);
            SqlDataAdapter sdr 
= new SqlDataAdapter(com);
            DataTable dataTable 
= new DataTable();
            
try
            {
                OpenCon();
                sdr.Fill(dataTable);
            }
            
catch (SqlException err)
            {
                
if (WriteLog)
                {
                    Log.WriteLog(err.Message);
                }
            }
            
finally
            {
                sdr.Dispose();
            }
            
return dataTable;
        }
复制代码

 

 

11:参数方法,无论是存储过程,还是传参型的sql语句,都要用到

A:参数增加:

复制代码
        internal void AddParameters(string parameterName, object value)
        {
            
if (!com.Parameters.Contains(parameterName))
            {
                com.Parameters.AddWithValue(parameterName, value);
            }
        }
        
internal void AddParameters(string parameterName, object value, SqlDbType sqlDbType)
        {
            
if (!com.Parameters.Contains(parameterName))
            {
                com.Parameters.Add(parameterName, sqlDbType).Value 
= value;
            }
        }
复制代码

 

B:参数清除:

复制代码
        internal void ClearParameters()
        {
            
if (com != null && com.Parameters != null)
            {
                com.Parameters.Clear();
            }
        }
复制代码

 

12:返回值属性,一般用于返回记录总数

复制代码
        private int returnValue;
        
public int ReturnValue
        {
            
get
            {
                
if (com != null && com.Parameters != null)
                {
                 
int.TryParse(Convert.ToString(com.Parameters["ReturnValue"].Value),out returnValue);
                }
                
return returnValue;
            }
            
set { returnValue = value; }
        }
复制代码

就此,SQLHelper 就算写完了,余下要处理一下日志记录与异常抛出。

 

13:Log类异常日志记录与抛出

复制代码
class Log
{
        
public static void WriteLog(string message)
        {
            
if (IsCanWrite())
            {
                
 InsertLogToData(message);
            }
            
else
            {
                
throw new Exception(message);
            }
        }
        
private static bool IsCanWrite()
        {
           
//从配置文件取
         }
        
private static void InsertLogToData(string message)
        {
            
//错误日志入库,可以自定义写文本或入数据库
         }
}
复制代码

判断是一下是否设置为可写日志,如果是则写,否则抛异常。

 

14:实现IsCanWrite方法

复制代码
private static bool IsCanWrite()
{

     
bool IsCanWriteLog;
     
bool.TryParse(Convert.ToString(ConfigurationManager.AppSettings["IsWriteLog"]), out IsCanWriteLog);
     
return IsCanWriteLog;
}
复制代码

从配置文件里取配置,如果配置为true,就记录日志,否则抛出异常。

 

插曲:写到这里,博客园又挂了,好在有预感之前保存了一下文章:上图:

十几分钟后,正常了!!!

 

15:实现InsertLogToData方法,将错误异常入库

复制代码
        private static void InsertLogToData(string message)
        {
            
//错误日志入库,可以自定义写文本或入数据库
            if (ConfigurationManager.ConnectionStrings["LogConn"== null)
            {
                
return ;
            }
            
string pageUrl = System.Web.HttpContext.Current.Request.Url.ToString();
            SQLHelper helper 
= new SQLHelper("LogConn");
            helper.WriteLog 
= false;//再产生错误就不写日志了,不能产生死循环
            try
            {
                helper.AddParameters(
"@PageUrl", pageUrl, System.Data.SqlDbType.NVarChar);
                helper.AddParameters(
"@ErrorMessage", message, System.Data.SqlDbType.NVarChar);
                helper.ExeNonQuery(
"insert into ErrorLogs(PageUrl,ErrorMessage) values(@PageUrl,@ErrorMessage)"false);
                helper.Dispose();
            }
            
catch
            {
               
//啥也不做了
            }
        }
复制代码

这里只是对ErrorLogs表进行插入数据操作,将当前发生错误的Url地址及错误信息插入表中。

同时也演示了一把SQLHelper的用法。当然你可以修改成自己需要的日志记录方法。

 

至此,想了一天,终于把这个SQLHelper类给写完了,虽然此类在本框架中不对外开放使用,不过有心的读者仍可以独立出去使用。

 

OK,本节也就到此结束了。欢迎读者留言讨论或提出建议!

 

后语:从你学会写或用SQLHelper那时起,你还会去界面写一堆的类似这样的代码吗?

复制代码
        SqlConnection con = new SqlConnection("server=.;database=CYQ;uid=sa;pwd=123456");
        SqlCommand com 
= new SqlCommand();
        com.Connection 
= con;
        com.CommandType 
= CommandType.Text;
        com.CommandText 
= "SELECT * FROM CYQTABLE WHERE ID=888";
        con.Open();
        SqlDataReader sdr
=com.ExecuteReader();
        
if (sdr != null)
        {
            
while (sdr.HasRows)
            {
                sdr.Read();
                
//...循环读...

            }
            sdr.Close();
        }
        con.Close();
复制代码

 

难了吧,回头已太难了,不管是基于认知度的提升还是开发效率上,你都基本不回头了吧。

 

如果有一天

你又认知了微软的ADO.NET Entity Framework或是NHibernate或其它框架。

又或者有一天

你原创框架了

又或是使用本框架了

你还会回头用那个曾经过的SQLHelper么

只能说,一切回头太难。

 

备注:完整框架源码会在本系列结束之后另开章节发布,暂时望勿激动,学习思想才是重要的。

版权声明:本文原创发表于 博客园,作者为 路过秋天 本文欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则视为侵权。
posted on 2010-08-25 10:09 路过秋天 阅读(3874) 评论(99) 编辑 收藏

发表评论
  
#51楼 2010-08-25 16:22 | 土豆烤肉  
一大把的
if (WriteLog)
{
Log.WriteLog(err.Message);
}

不知道优化一下么
  
#52楼[楼主] 2010-08-25 16:30 | 路过秋天  
@ 土豆烤肉
两行代码,怎么优化简短些?欢迎解说下。
关于if里的WriteLog,在日志记录里是有作用的,避免进入死循环。
  
#53楼 2010-08-25 18:56 | 金色海洋(jyk)阳光男孩  
如果有一天

你又认知了微软的ADO.NET Entity Framework或是NHibernate或其它框架。

又或者有一天

你原创框架了

又或是使用本框架了

你还会回头用那个曾经过的SQLHelper么

只能说,一切回头太难。


===============

不存在什么回头不回头的问题。

如果从头到尾,从一开始到将来,都是自己写(代码/框架)的话,那么就没有什么回不回头的问题。

因为以前写的,是现在的一个基石。


ADO.NET Entity Framework 内部就没有类似SQLHelp的东东吗?
至少会有ADO.net吧。

至于为什么给我们的感觉,调用的方法不一样了?

那是因为不是我们自己写的,不是我们自己升级的。

  
#54楼 2010-08-25 19:23 | NeilChen  
赞同自己写框架,对水平是个很好的锻炼。但是也要善于学习已有的框架里先进的思想/编程技巧,以为己用。
  
#55楼[楼主] 2010-08-25 22:23 | 路过秋天  
@ 木野狐(Neil Chen)
其实本框架2007年就完成的,最近只是拿出来升下级改造一下。
  
#56楼 2010-08-25 23:45 | 路过,歌好听
歌好听
  
#57楼[楼主] 2010-08-26 00:03 | 路过秋天  
@ 路过,歌好听
左上角的音乐终于被你首个发现了,恭喜恭喜!
  
#58楼 2010-08-26 09:55 | Framework  
引用路过秋天:
@Framework
代码质量太差了?那纠正下代码再走不迟~
说我在误导,至少表明下怎么样才不算误导吧?
没说SqlHelper不值的学习,很多人都是从sqlhelper过来的。

你看看SqlHelper的代码怎么写的,再看看你的,细节地方就不说了
你写这篇文章的不就是为了说明SqlHelper过时了吗?这个难道不算误导吗?
  
#59楼 2010-08-26 09:59 | 深蓝医生  
昨天看了看没有人回复,今天居然有这么多人回复了,恭喜楼主。
今天又仔细看了楼主的博文,结合大家的回复,我觉得有两个方面需要注意:
1,全局变量的使用,比如你的com对象,虽然理论上面说每次使用SQLHelper的时候new一个出来,但很多开发人员没有这个习惯,喜欢new一个以后一直用着,这样在多线程中很容易出现问题,我们公司曾经出现过这样的问题;
2,对事务的处理,实际上一个数据访问对象功能是否强大关键要看事务处理能力了,比如先New一个SQLHelper,一直用着,一部分代码没有使用事务,一部分使用了事务,就很可能出现冲突,另外,如果你有多个业务组件来调用你的SQLHelper,那么这些组件之间的事务协调是很麻烦的。

线程安全和事务处理是企业级数据组件重点关注的问题!
  
#60楼[楼主] 2010-08-26 10:01 | 路过秋天  
@ Framework
晕,要是这篇文章是为了说明sqlhelper过时了,上面还那么多讨论代码的干虾米哦。
同样,要是写sqlhelper过时的文章,用得着上代码么,直接写文字型的忽悠型文章就行了。
  
#61楼[楼主] 2010-08-26 10:11 | 路过秋天  
@ 深蓝医生
:) smile
刚准备发布V1.4版本呢,看了你的回复之后,看来得加上事务功能了。
  
#62楼 2010-08-26 10:12 | 兽王俾斯麦  
真的很误导人啊!
  
#63楼 2010-08-26 10:13 | 深蓝医生  
实际上,如果采用良好的设计模式(最简单的就是工厂模式),那么扩展支持多种数据库非常简单,例如PDF.NET数据开发框架对SQLite数据访问的扩展:
  
#64楼[楼主] 2010-08-26 10:23 | 路过秋天  
@ 兽王俾斯麦
-_-...看来得编辑下文章加点注释解释下才得。
  
#65楼[楼主] 2010-08-26 10:26 | 路过秋天  
@ 深蓝医生
如果是单独的SQLHelper,是可以扩展支持多种数据库的,只是本框架中,内部主查询都为存储过程分页及数据结构的构成,都限制了,所以支持不了access,所以,本SQLHelper加扩展反而多此一举了,不过目前支持多数据库的还是应用的挺广泛的。
  
#66楼 2010-08-26 16:35 | 陈梓瀚(vczh)  
@ 兽王俾斯麦
知道“学了再用”的前提是什么吗,就是你之前已经花了很长时间学一些“本来可以以后再学”的东西,然后你的学习速度已经非常快了,然后你就可以安心地“学了再用”了。因此到了这个地步,你什么都不用学,立刻上,开MSDN,要什么查什么,就是这个意思。当然这仅仅是说类库,功力你还是要有的……
  
#67楼 2010-08-26 16:57 | 兽王俾斯麦  
什么叫“本来可以以后再学”?我对你很不了解?
  
#68楼 2010-09-07 22:22 | [兴华]  
@ 路过秋天

你这水平的就老实呆着吧...没事儿出来现什么啊 误导初学者
  
#69楼 2010-09-07 22:30 | [兴华]  
又仔细看了看, 满目疮痍...

LZ赶紧歇了吧...
  
#70楼[楼主] 2010-09-07 23:22 | 路过秋天  
@ [兴华]
说句不好听的,你妈喊你回家吃饭了。
  
#71楼 2010-09-08 12:01 | [兴华]  
@ 路过秋天
既然你说了句不好听的 我就让你明白明白
首先, 就从你的helper类说起, 首先说说什么叫helper类. Helper类是组合了一些方法的类, 这些方法跟应用程序的逻辑无关. 在MVC框架里我们见过HtmlHelpers. 通常, Helper类的方法大多数是静态的, 因为在一般情况下helper类不需要扩展. 也就是说当且仅当helper类需要扩展的时候才将它设计成可实例化的形式. 你的helper类扩展了吗? EnterpriseLibrary里的helper类是静态化的, 你为啥偏偏出一个可实例化的? 从哪能解释的通?
关于helper类的讨论: http://blogs./b/nickmalik/archive/2005/09/06/461404.aspx
http://blogs./b/nickmalik/archive/2005/09/06/461404.aspx

其次, 说说你的命名. 按照C#的命名标准, 应该是Sql而不是SQL. 这点在.NET类库里已经体现. 还有你程序里conn, Con不分, 这又是何意?
<代码大全>里曾经说过缩写一个单词的准则, 一般来讲只有字母少于一半的缩写才值得缩写, connetion -> conn 可以, 而且值得, conn -> con 不知道你是为何.
微软的命名规范 有时间看看
http://msdn.microsoft.com/en-us/library/czefa0ke%28vs.71%29.aspx

第三, IsCanWrite和InsertLogToData这两个方法的命名有问题, 说明你英文水平不是很好. 先前看过alibaba的一份关于html页面class/id的命名规则, 能用英文的尽量用英文, 但是必须地道, 否则请用拼音. Is/Can 这两个词放一起 够让人笑掉大牙的了吧, InsertLogToDb貌似比ToData更好些吧.

第四: 楼上有人劝你用using,这是语言赋予你的自动清除垃圾的简洁优雅的语法, Effective C#里不止一次强调要尽量用这种语法而不是自己去Dispose, 你怎么就是不听? 不是误导新人是什么?

还有就是楼上诸君提到的, 这里恕不赘述.

我说你, 不是为了争什么, 也不是彰显自己水平有多高. 就是看不太管你这种半瓶子咣当的就忙不及出来写文章, 非要写, 可以在家自己写, 别往网上发, 否则误人子弟的责任你担得起么!

如果有要讨论的欢迎加我QQ:66074915. 并无敌意, 不打不相识
  
#72楼[楼主] 2010-09-08 13:04 | 路过秋天  
@ [兴华]
问题1:Helper类的方法大多数是静态的,是,很网上有很多是静态的,可是这规定是死的?谁家定死一定要静态,不静态就误人了?我的类扩展了吗?你看过这个类在框架的里的使用了?没看赶紧看了再说话。
问题2:C#命名没有标准,只有规范,只是参考的规范。我整体规范偏离一般的规范很远么?你就这么纠住一两个词说个天大的事一样?
问题3:方法起名我起的没地道的英文怎么了?妨碍到大家的阅读与理解了么?这么多个看贴的,几个像你这样笑掉大牙的?
问题4:用using,最终的结果还是调用Disponse方法,再说本类也支持这种写法,我提醒大伙手动调用链接关闭咋了?有多人新手懂的using的原理,老是这么用只会造成是也这么用,不是也这么用。

最后总结一下:你有点像读死书的人,不是考了研还是读了博吧?
如果讨论,欢迎继续,并无敌意,只是坚持下自己的论点。
  
#73楼 2010-09-08 18:04 | [兴华]  
冥顽不灵...
  
#74楼 2010-09-08 18:23 | 好搞
@ [兴华]
你好搞。啊
  
#75楼[楼主] 2010-09-08 20:34 | 路过秋天  
@ [兴华]
欢迎您写出大作来普渡众生~
  
#76楼 2010-11-04 14:54 | zhourui  
我要返回存储过程里面的输出参数你,这个数据层无法做到?
  
#77楼[楼主] 2010-11-04 15:13 | 路过秋天  
@ zhourui
此sqlhelper默认用return value来返回单个值。
  
#78楼 2010-11-04 15:35 | zhourui  
还是不明白,因为我在用你的持久层,假如我要返回存储过程名为AA的ID,应该调用那个方法,你回复的真是迅速啊
  
#79楼[楼主] 2010-11-04 18:44 | 路过秋天  
@ zhourui
对于存储过程,一般都为以下情况:
1:返回结果集,附带记录总数。
用ExeDataTable()方法之后,直接取ReturnValue
2:返回记个记录
用ExeScalar
3:不返回或返回受影响行数
ExeNonQuery
--------
以上,都和SqlCommand是基本一致的。
  
#80楼 2011-05-06 09:23 | xyyie  
public SQLHelper()
{
if (ConfigurationManager.ConnectionStrings["Conn"] != null)
{
_con = new SqlConnection(ConfigurationManager.ConnectionStrings["Conn"].ConnectionString);
com.Connection = con;
}

}


这句 "com.Connection = con; "应该是
com.Connection = _con;
  
#81楼[楼主] 2011-05-06 09:35 | 路过秋天  
@ xyyie
还是你看的仔细,这就编辑下。
  
#82楼 2011-06-07 22:35 | zeyoo  
在web.config中配置数据库连接是不是有两种方法?一种是通过<appSettings>,一种是通过<connectionStrings>,用哪一种方法好?
  
#83楼[楼主] 2011-06-07 23:50 | 路过秋天  
@ zeyoo
后一种。
  
#84楼 2011-06-08 22:48 | zeyoo  
不明白为什么要多写一个构造函数public SQLHelper(string conn),它有什么用吗?而且不明白为什么要conn.Length<25.这跟长度有什么关系?
  
#85楼 2011-06-08 23:26 | zeyoo  
10:实现封装的几个方法,异常则记录日志/抛出
第二个函数 internal object ExeScalar(string procName)
第一行 SetCommandText(procName, isProc)
中参数isProc在这个函数中没有出现过.
  
#86楼[楼主] 2011-06-09 00:45 | 路过秋天  
引用zeyoo:不明白为什么要多写一个构造函数public SQLHelper(string conn),它有什么用吗?而且不明白为什么要conn.Length<25.这跟长度有什么关系?

这只是一种基础的判断方式,可以接收长长的数据库链接,或简单的web.config中的一个配置项名称,这个代码中可以看出来。
  
#87楼[楼主] 2011-06-09 00:46 | 路过秋天  
引用zeyoo:
10:实现封装的几个方法,异常则记录日志/抛出
第二个函数 internal object ExeScalar(string procName)
第一行 SetCommandText(procName, isProc)
中参数isProc在这个函数中没有出现过.

写少了一个参数名,被你发现了。
  
#88楼 2011-06-09 08:17 | zeyoo  
引用路过秋天:
引用zeyoo:
10:实现封装的几个方法,异常则记录日志/抛出
第二个函数 internal object ExeScalar(string procName)
第一行 SetCommandText(procName, isProc)
中参数isProc在这个函数中没有出现过.

写少了一个参数名,被你发现了。

那赶紧改过来吧,还有 9:我们封装一下SqlCommand的几个执行返回 下的这个函数
  
#89楼[楼主] 2011-06-09 13:00 | 路过秋天  
@ zeyoo
已经编辑了。
  
#90楼 2011-06-09 19:31 | zeyoo  
又发现了一个问题:
13:Log类异常日志记录与抛出
第4行:return InsertLogToData(message);
多了一个return,因为函数InsertLogToData(message)没有返回值。
  
#91楼[楼主] 2011-06-09 20:11 | 路过秋天  
@ zeyoo
又编辑了。
  
#92楼 2011-06-09 22:03 | zeyoo  
本人菜鸟,问一个简单的问题。
你把ExeNonQuery(),ExeScalar(),ExeDataReader(),ExeDataTable()几个方法都定义成了internal,定义成internal只能在内部访问,我在另一个.cs文件中就不能访问了,最后还是把它们改成了public,请问这里是笔误呢还是故意定义成inertnal的。
知道你比较忙,有时间就回吧,谢谢!
  
#93楼[楼主] 2011-06-10 01:35 | 路过秋天  
@ zeyoo
因为这个类在CYQ.Data中内部的才用到,不对外使用,所以是internal,你的要对外使用,用public是对的。
  
#94楼 2011-08-08 21:39 | 木子家  
看过了,感觉还是使用sqlhelper好
  
#95楼[楼主] 2011-08-08 23:11 | 路过秋天  
@ alxc
有个过程,先习惯sqlhelper也是种习惯。
  
#96楼 2011-08-09 09:53 | 木子家  
@ 路过秋天
我之前自己写的oraclehelper和你的差不错,经过3个项目后,还是觉得sqlhelper比较好用。
  
#97楼 2012-05-04 16:23 | koi  
3:既然要实例化才调用,那我们只需要一个Command和一个链接就可以了,所以,我们把它们拿到外面定义成全局变量??
那为什么SqlDataReader 不也定义到全局
  
#98楼[楼主] 2012-05-06 20:20 | 路过秋天  
@ koi
这么旧的文章你还回复。
sqldatareader不一定会被用到,只能这么答你。
  
#99楼 2012-08-22 10:30 | 玉菜园  
SQLHelper还是不错的

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约