.net(C#)在Access数据库中执行sql脚本
自己写的一个工具类,主要是业务场景的需要。
主要有两个功能:
调用方式
/// <summary>
/// 执行sql语句
/// </summary>
/// <param name="sql">需要执行的sql语句</param>
public bool ExecuteSql(string sql, ref string errorMsg)
{
SetConnOpen();
string[] sqls = serializeSql(sql);
OleDbTransaction tran = conn.BeginTransaction();
try
{
comm = new OleDbCommand();
comm.Transaction = tran;
comm.Connection = conn;
foreach (string s in sqls)
{
var temps = s.Trim().Replace("\r\n", "");
if (!string.IsNullOrEmpty(temps))
{
comm.CommandText = temps;
comm.ExecuteNonQuery();
}
}
tran.Commit();
return true;
}
catch(Exception ex)
{
tran.Rollback();
errorMsg = ex.Message;
return false;
}
finally
{
conn.Close();
}
}
执行包含sql语句的字符串
/// <summary>
/// 从sql脚本文件执行
/// </summary>
/// <param name="sqlFilePath">sql脚本文件的路径</param>
/// <returns></returns>
public bool ExecuteSqlByFile(string sqlFilePath,ref string errorMsg)
{
if(!File.Exists(sqlFilePath))
{
throw new FileNotFoundException("未找到该sql脚本,请检查路径是否错误");
} string sourceSql = new StreamReader(sqlFilePath).ReadToEnd();
string[] sqls = serializeSql(sourceSql);
SetConnOpen();
OleDbTransaction tran = conn.BeginTransaction();
try
{
comm = new OleDbCommand();
comm.Transaction = tran;
comm.Connection = conn;
foreach (string s in sqls)
{
var temps = s.Trim().Replace("\r\n", "");
if (!string.IsNullOrEmpty(temps))
{
comm.CommandText = temps;
comm.ExecuteNonQuery();
}
}
tran.Commit();
return true;
}
catch (Exception ex)
{
tran.Rollback();
errorMsg = ex.Message;
return false;
}
finally
{
conn.Close();
}
}
/// <summary>
/// 将sql脚本进行序列化
/// </summary>
/// <param name="sql">sql脚本</param>
/// <returns></returns>
private string[] serializeSql(string sql)
{
string[] ss = sql.Split(new string[] { "/*go*/" }, StringSplitOptions.RemoveEmptyEntries);
return ss;
}
执行包含sql语句的文件
其实思路比较简单,就是将sql语句用字符串进行分割,然后将一条条sql语句组合成一个数组,依次进行执行即可。在执行过程中使用事务处理,当错误发生时,能够进行回滚操作。下面是完整代码:
AccessUtils.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using System.Data.OleDb;
using System.Data.OleDb;
using System.IO;
using System.Data; namespace AccessRuntime.Bin
{
/// <summary>
/// Access工具类
/// </summary>
internal sealed class AccessUtils
{
/// <summary>
/// access数据库连接字符串
/// </summary>
private string accessConnectionString = string.Empty;
/// <summary>
/// access数据库连接对象
/// </summary>
private OleDbConnection conn;
/// <summary>
/// access数据库命令对象
/// </summary>
private OleDbCommand comm;
/// <summary>
/// access数据库连接字符串
/// </summary>
public string AccessConnectionString
{
get {
if (!string.IsNullOrEmpty(accessConnectionString))
return accessConnectionString;
else
{
string connstr = ConfigurationManager.ConnectionStrings["AccessRuntimeConnectionString"].ConnectionString;
if (string.IsNullOrEmpty(connstr))
throw new ConnectionStringElementNotFindException("未找到或未设置AccessRuntimeConnectionString节点");
else
return connstr;
}
}
}
/// <summary>
/// 初始化连接(有密码)
/// </summary>
/// <param name="filepath">可以为空,为空则调用配置文件</param>
/// <param name="pwd">数据库密码</param>
/// <example>
/// public AccessUtils("123",null)
/// </example>
public AccessUtils(string pwd,string filepath)
{
if (string.IsNullOrEmpty(filepath))
{
filepath = AccessConnectionString;
}
this.conn = new OleDbConnection(filepath + "; Jet OLEDB:Database Password=" + pwd);
conn.Open();
} /// <summary>
/// 初始化连接(无密码)
/// </summary>
/// <param name="filepath"></param>
/// <example>
/// 1.public AccessUtils(filepath)
/// 2.public AccessUtils()//不传递参数则调用配置文件
/// </example>
public AccessUtils(string filepath = null)
{
if (string.IsNullOrEmpty(filepath))
{
filepath = AccessConnectionString;
}
this.conn = new OleDbConnection(filepath);
conn.Open();
} /// <summary>
/// 执行sql语句
/// </summary>
/// <param name="sql">需要执行的sql语句</param>
public bool ExecuteSql(string sql, ref string errorMsg)
{
SetConnOpen();
string[] sqls = serializeSql(sql);
OleDbTransaction tran = conn.BeginTransaction();
try
{
comm = new OleDbCommand();
comm.Transaction = tran;
comm.Connection = conn;
foreach (string s in sqls)
{
var temps = s.Trim().Replace("\r\n", "");
if (!string.IsNullOrEmpty(temps))
{
comm.CommandText = temps;
comm.ExecuteNonQuery();
}
}
tran.Commit();
return true;
}
catch(Exception ex)
{
tran.Rollback();
errorMsg = ex.Message;
return false;
}
finally
{
conn.Close();
}
}
/// <summary>
/// 从sql脚本文件执行
/// </summary>
/// <param name="sqlFilePath">sql脚本文件的路径</param>
/// <returns></returns>
public bool ExecuteSqlByFile(string sqlFilePath,ref string errorMsg)
{
if(!File.Exists(sqlFilePath))
{
throw new FileNotFoundException("未找到该sql脚本,请检查路径是否错误");
} string sourceSql = new StreamReader(sqlFilePath).ReadToEnd();
string[] sqls = serializeSql(sourceSql);
SetConnOpen();
OleDbTransaction tran = conn.BeginTransaction();
try
{
comm = new OleDbCommand();
comm.Transaction = tran;
comm.Connection = conn;
foreach (string s in sqls)
{
var temps = s.Trim().Replace("\r\n", "");
if (!string.IsNullOrEmpty(temps))
{
comm.CommandText = temps;
comm.ExecuteNonQuery();
}
}
tran.Commit();
return true;
}
catch (Exception ex)
{
tran.Rollback();
errorMsg = ex.Message;
return false;
}
finally
{
conn.Close();
}
}
/// <summary>
/// 将sql脚本进行序列化
/// </summary>
/// <param name="sql">sql脚本</param>
/// <returns></returns>
private string[] serializeSql(string sql)
{
string[] ss = sql.Split(new string[] { "/*go*/" }, StringSplitOptions.RemoveEmptyEntries);
return ss;
}
/// <summary>
/// 获取打开的连接
/// </summary>
private void SetConnOpen()
{
if (this.conn.State != ConnectionState.Open)
{
this.conn.Open();
}
}
}
}
AccessUtils.cs
AccessTool.cs 这个是对AccessUtils类的封装,提供了更加友好的方法。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace AccessRuntime.Bin
{
/// <summary>
/// Access工具
/// 注意:语句之间使用 /*go*/ 进行分割
/// </summary>
public static class AccessTool
{
/// <summary>
/// 在Access数据库中执行sql语句
/// </summary>
/// <param name="sql">sql脚本</param>
/// <param name="pwd">数据库密码(如果无密码则不填写此参数)</param>
/// <returns>执行结果</returns>
public static bool ExecuteSql(string sql,string pwd = null)
{
AccessUtils au = null;
if (string.IsNullOrEmpty(pwd)) {
au = new AccessUtils();
string msg = null;
if(au.ExecuteSql(sql, ref msg))
{
return true;
}
else
{
throw new AccessRuntimeException(msg);
}
}
else
{
au = new AccessUtils(pwd, null);
string msg = null;
if(au.ExecuteSql(sql,ref msg))
{
return true;
}
else
{
throw new AccessRuntimeException(msg);
}
} } /// <summary>
/// 在Access数据库中执行sql脚本
/// </summary>
/// <param name="sqlpath">sql脚本路径</param>
/// <param name="pwd">数据库密码(如果无密码则不填写此参数)</param>
/// <returns>执行结果</returns>
public static bool ExecuteSqlByFile(string sqlpath,string pwd = null)
{
AccessUtils au = null;
//判断密码是否填写
if (string.IsNullOrEmpty(pwd))
{
au = new AccessUtils();
string msg = null;
if (au.ExecuteSqlByFile(sqlpath, ref msg))
{
return true;
}
else
{
throw new AccessRuntimeException(msg);
}
}
else
{
au = new AccessUtils(pwd, null);
string msg = null;
if (au.ExecuteSqlByFile(sqlpath, ref msg))
{
return true;
}
else
{
throw new AccessRuntimeException(msg);
}
}
} /// <summary>
/// 在指定Access数据库中执行sql语句
/// </summary>
/// <param name="sql">sql脚本</param>
/// <param name="dbpath">数据库所在路径</param>
/// <param name="pwd">执行结果</param>
/// <returns></returns>
public static bool OnExecuteSql(string sql,string dbpath,string pwd = null)
{
AccessUtils au = null;
if (string.IsNullOrEmpty(pwd))
{
au = new AccessUtils(dbpath);
string msg = null;
if (au.ExecuteSql(sql, ref msg))
{
return true;
}
else
{
throw new AccessRuntimeException(msg);
}
}
else
{
au = new AccessUtils(pwd, dbpath);
string msg = null;
if (au.ExecuteSql(sql, ref msg))
{
return true;
}
else
{
throw new AccessRuntimeException(msg);
}
} } /// <summary>
/// 在指定Access数据库中执行sql语句
/// </summary>
/// <param name="sqlpath">sql脚本路径</param>
/// <param name="dbpath">数据库所在路径</param>
/// <param name="pwd">执行结果</param>
/// <returns></returns>
public static bool OnExecuteSqlByFile(string sqlpath, string dbpath, string pwd = null)
{
AccessUtils au = null;
//判断密码是否填写
if (string.IsNullOrEmpty(pwd))
{
au = new AccessUtils(dbpath);
string msg = null;
if (au.ExecuteSqlByFile(sqlpath, ref msg))
{
return true;
}
else
{
throw new AccessRuntimeException(msg);
}
}
else
{
au = new AccessUtils(pwd, dbpath);
string msg = null;
if (au.ExecuteSqlByFile(sqlpath, ref msg))
{
return true;
}
else
{
throw new AccessRuntimeException(msg);
}
}
}
}
}
AccessToo.cs
本工具中还定义了两个自定义的异常类:AccessRuntimeException.cs,ConnectionStringElementNotFindException.cs,下付代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace AccessRuntime.Bin
{
/// <summary>
/// AccessRuntime异常
/// </summary>
public class AccessRuntimeException:Exception
{
/// <summary>
/// 配置文件节点未找到
/// </summary>
public AccessRuntimeException()
{ }
/// <summary>
/// 配置文件节点未找到
/// </summary>
/// <param name="message">异常信息</param>
public AccessRuntimeException(string message):base(message)
{ }
/// <summary>
///
/// </summary>
/// <param name="message">异常信息</param>
/// <param name="inner">异常类</param>
public AccessRuntimeException(string message, Exception inner)
: base(message, inner)
{ }
}
}
AccessRuntimeException.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace AccessRuntime.Bin
{
/// <summary>
/// 配置文件节点未找到
/// </summary>
internal class ConnectionStringElementNotFindException:Exception
{
/// <summary>
/// 配置文件节点未找到
/// </summary>
public ConnectionStringElementNotFindException()
{ }
/// <summary>
/// 配置文件节点未找到
/// </summary>
/// <param name="message">异常信息</param>
public ConnectionStringElementNotFindException(string message):base(message)
{ }
/// <summary>
///
/// </summary>
/// <param name="message">异常信息</param>
/// <param name="inner">异常类</param>
public ConnectionStringElementNotFindException(string message, Exception inner)
: base(message, inner)
{ }
}
}
ConnectionStringElementNotFindException.cs
注意:
1.使用本代码时,需要配置config文件,需要添加AccessRuntimeConnectionString的ConnectionString节点,进行Access数据库配置,当然你也可以根据自己的需要进行调整。
2.在本工具中各个sql语句间使用/*go*/进行分隔,类似mssql中的go(批处理)一样。
.net(C#)在Access数据库中执行sql脚本的更多相关文章
- InstallShield在MySQL和Oracle中执行SQL脚本的方法InstallShield在MySQL和Oracle中执行SQL脚本的方法
简述 InstallShield已经内建了对MySQL和Oracle的支持.但是这个功能是通过ODBC实现的,它对SQL脚本的格式要求非常严格,因此已经通过官方客户端测试的脚本在IS中执行时往往就会报 ...
- Eclipse中执行sql脚本文件
转自:https://blog.csdn.net/weixin_37778823/article/details/79614281 在Eclipse中导入或新建sql脚本文件(.sql文件),选择指定 ...
- navicat 中执行sql脚本 喊中文错误
执行内容和上篇一样,只是换了工具. 执行成功,但是数据库对应中文没有内容. sql脚本的编码是asci 执行的时候选择gbk 编码
- shell脚本中执行sql脚本(mysql为例)
1.sql脚本(t.sql) insert into test.t value ("LH",88); 2.shell脚本(a.sh 为方便说明,a.sh与t.sql在同一目 ...
- 2016.1.23 通过cmd在程序中执行sql脚本
System.Diagnostics.Process pro = new System.Diagnostics.Process(); pro.StartInfo.FileName = "cm ...
- shell脚本中执行sql脚本并传递参数(mysql为例)
1.mysql脚本文件 t.sql insert into test.t values(@name,@age); exit 2.shell脚本文件 a.sh (为方便演示,与t.sql文件放在同一目 ...
- mysql数据库批量执行sql文件对数据库进行操作【windows版本】
起因: 因工作需要,在本机测试环境升级mysql数据库,需逐条执行mysql数据库的sql文件对数据库进行升级,因此找了些关于mysql的文章,对批量升级数据库所需的sql文件进行升级. 整理思路: ...
- 用SQL语句创建和删除Access数据库中的表;添加列和删除列
用SQL语句创建和删除Access数据库中的表;添加列和删除列 Posted on 2009-08-11 13:42 yunbo 阅读(1240) 评论(0) 编辑 收藏 用SQL语句创建和删除Acc ...
- 在SQL Server数据库中执行存储过程很快,在c#中调用很慢的问题
记录工作中遇到的问题,分享出来: 原博客地址:https://blog.csdn.net/weixin_40782680/article/details/85038281 今天遇到一个比较郁闷的问题, ...
随机推荐
- 网站开发进阶(二十九)HTML特殊转义字符
HTML特殊转义字符 参考文献 http://tool.oschina.net/commons?type=2 美文美图
- LayoutInflater和inflate的用法,有图有真相
1.概述 有时候在我们的Activity中用到别的layout,并且要对其组件进行操作,比如: A.acyivity是获取网络数据的,对应布局文件为A.xml,然后需要把这个数据设置到B.xml的组件 ...
- JSP判断移动设备
日期: 2014年3月6日 人员::铁锚 看到了一篇很好的文章, <在天猫,前端做什么?>,里面有天猫php判断移动设备的正则(个人猜测),觉得很好用,于是就决定移植到JSP里面. jsp ...
- android 常用方法集合
private static Contextcontext; privatestatic Displaydisplay; private static String TAG = "MyToo ...
- Linux管理日记(三)
23. 时间同步 同步时间可以使用 root 执行如下命令完成: rdate -s time.nist.gov 如果需要自动同步,可以采用crontab自动调度,每小时执行一次: 编辑 cronta ...
- 程序员编程艺术:第三章续、Top K算法问题的实现
程序员编程艺术:第三章续.Top K算法问题的实现 作者:July,zhouzhenren,yansha. 致谢:微软100题实现组,狂想曲创作组. 时间:2011年05月08日 ...
- Cursor类取出数据
重点是要调用 moveToFirst(); long id=intent.getLongExtra("id",0); Cursor cr =dbh.selectDataById(i ...
- Android特效专辑(八)——实现心型起泡飞舞的特效,让你的APP瞬间暖心
Android特效专辑(八)--实现心型起泡飞舞的特效,让你的APP瞬间暖心 马上也要放年假了,家里估计会没网,更完这篇的话,可能要到年后了,不过在此期间会把更新内容都保存在本地,这样有网就可以发表了 ...
- IP网际协议 - IP首部,IP路由选择,子网掩码
IP首部 4个字节的32 bit值以下面的次序传输:首先是0-7 bit,其次8-15 bit,然后1 6-23 bit,最后是24~31 bit.这种传输次序称作big endian字节序.由于T ...
- Dijkstra算法 c语言实现
Dijkstra(迪杰斯特拉)算法是典型的最短路径路由算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.Dijkstra算法能得出最短路径的最优 ...