.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 今天遇到一个比较郁闷的问题, ...
随机推荐
- 【算法导论】图的深度优先搜索遍历(DFS)
关于图的存储在上一篇文章中已经讲述,在这里不在赘述.下面我们介绍图的深度优先搜索遍历(DFS). 深度优先搜索遍历实在访问了顶点vi后,访问vi的一个邻接点vj:访问vj之后,又访问vj的一个邻接点, ...
- RecyclerView实现瀑布流效果(二)
在上篇中我们知道RecyclerView中默认给我们提供了三种布局管理器,分别是LinearLayoutManager.GridLayoutManager.StaggeredGridLayoutMan ...
- 【翻译】Ext JS最新技巧——2014-9-10
原文:Top Support Tips Greg Barry:删除网格单元格的焦点 在Ext JS 5.0.1,添加了一些与可访问性和支持ARIA有关的显著改进.虽然鼓励使用这些新增功能,但默认样式可 ...
- (三十三)Xcode项目的重要工程文件
1.Supporting files内有一个Xxx-Info.plist文件(旧版本Xcode的配置文件叫Info.plist).因此自定义的plist不要带Info关键词. 这个plist是系统的全 ...
- FPGA学习笔记(一)Verilog语法基础
一.变量类型 ①数值 数值表示采用 <二进制位数>'<数值表示的进制><数值>的结构. 其中进制可以为b.o.d.h分别代表二.八.十.十六进制. 例如22'd0代 ...
- Lucene 学习资料
个机制的结合.关于中文的语言分析算法,大家可以在Google查关键词"wordsegment search"能找到更多相关的资料. 安装和使用 下载:http://jakarta. ...
- Android实训案例(二)——Android下的CMD命令之关机重启以及重启recovery
Android实训案例(二)--Android下的CMD命令之关机重启以及重启recovery Android刚兴起的时候,着实让一些小众软件火了一把,切水果,Tom猫,吹裙子就是其中的代表,当然还有 ...
- Mina源码阅读笔记(二)- IoBuffer的封装
在阅读IoBuffer源码之前,我们先看Mina对IoBuffer的描述:A byte buffer used by MINA applications. This is a replacement ...
- mybatis ---- 实现数据的增删改查
前面介绍了接口方式的编程,需要注意的是:在book.xml文件中,<mapper namespace="com.mybatis.dao.IBookDao"> ,命名空间 ...
- obj-c编程13:归档
这篇归档内容的博文也挺有趣的,笨猫对好玩的东西一向感兴趣啊!如果用过ruby就会知道,obj-c里的归档类似于ruby中的序列化概念,不过从语法的简洁度来说,我只能又一次呵呵了. 下面大家将会看到2种 ...