public   void   Create(   string   mdbPath   ) 
 { 
 if(   File.Exists(mdbPath)   )   //检查数据库是否已存在 
 { 
 throw   new   Exception( "目标数据库已存在,无法创建 "); 
 } 
 //   可以加上密码,这样创建后的数据库必须输入密码后才能打开 
 mdbPath   =   "Provider=Microsoft.Jet.OLEDB.4.0;Data   Source= "   +   mdbPath; 
 //   创建一个CatalogClass对象的实例, 
 ADOX.CatalogClass   cat   =   new   ADOX.CatalogClass(); 
 //   使用CatalogClass对象的Create方法创建ACCESS数据库 
 cat.Create(mdbPath); 
 } ///压缩修复ACCESS数据库,mdbPath为数据库绝对路径 
 public   void   Compact(   string   mdbPath   ) 
 { 
 if(   !File.Exists(mdbPath)   )   //检查数据库是否已存在 
 { 
 throw   new   Exception( "目标数据库不存在,无法压缩 "); 
 } 
 //声明临时数据库的名称 
 string   temp   =   DateTime.Now.Year.ToString(); 
 temp   +=   DateTime.Now.Month.ToString(); 
 temp   +=   DateTime.Now.Day.ToString(); 
 temp   +=   DateTime.Now.Hour.ToString(); 
 temp   +=   DateTime.Now.Minute.ToString(); 
 temp   +=   DateTime.Now.Second.ToString()   +   ".bak "; 
 temp   =   mdbPath.Substring(0,   mdbPath.LastIndexOf( "// ")+1)   +   temp; 
 //定义临时数据库的连接字符串 
 string   temp2   =   "Provider=Microsoft.Jet.OLEDB.4.0;Data   Source= "   +   temp; 
 //定义目标数据库的连接字符串 
 string   mdbPath2   =   "Provider=Microsoft.Jet.OLEDB.4.0;Data   Source= "   +   mdbPath; 
 //创建一个JetEngineClass对象的实例 
 JRO.JetEngineClass   jt   =   new   JRO.JetEngineClass(); 
 //使用JetEngineClass对象的CompactDatabase方法压缩修复数据库 
 jt.CompactDatabase(   mdbPath2,   temp2   ); 
 //拷贝临时数据库到目标数据库(覆盖) 
 File.Copy(   temp,   mdbPath,   true   ); 
 //最后删除临时数据库 
 File.Delete(   temp   );   
 }///   备份数据库,mdb1,源数据库绝对路径;   mdb2:   目标数据库绝对路径   
 public   void   Backup(   string   mdb1,   string   mdb2   ) 
 { 
 if(   !File.Exists(mdb1)   ) 
 { 
 throw   new   Exception( "源数据库不存在 "); 
 } 
 try 
 { 
 File.Copy(   mdb1,   mdb2,   true   ); 
 } 
 catch(   IOException   ixp   ) 
 { 
 throw   new   Exception(ixp.ToString()); 
 } 
 }///恢复数据库,mdb1为备份数据库绝对路径,mdb2为当前数据库绝对路径 
 public   void   Recover(   string   mdb1,   string   mdb2   ) 
 { 
 if(   !File.Exists(mdb1)   )   
 { 
 throw   new   Exception( "备份数据库不存在 ");   
 } 
 try 
 { 
 File.Copy(   mdb1,   mdb2,   true   ); 
 } 
 catch(   IOException   ixp   ) 
 { 
 throw   new   Exception(ixp.ToString()); 
 } 
 }

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

使用ADOX创建Access数据库和表

using System;
 using ADOX;namespace WebPortal
 {
  /// <summary>
  /// CreateAccessDB 的摘要说明。
  /// 对于不同版本的ADO,需要添加不同的引用
   /// 请添加引用Microsoft ADO Ext. 2.7 for DDL and Security
   /// 请添加引用Microsoft ADO Ext. 2.8 for DDL and Security
  /// </summary>
  public class CreateAccessDB : System.Web.UI.Page
  {
     private void Page_Load(object sender, System.EventArgs e)
     {
       //为了方便测试,数据库名字采用比较随机的名字,以防止添加不成功时还需要重新启动IIS来删除数据库。
       string dbName = "D://NewMDB"+DateTime.Now.Millisecond.ToString()+".mdb";
       ADOX.CatalogClass cat = new ADOX.CatalogClass();
       cat.Create("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + dbName +";"); 
       Response.Write("数据库:" + dbName + "已经创建成功!");
       ADOX.TableClass tbl = new ADOX.TableClass();
       tbl.ParentCatalog = cat;
       tbl.Name="MyTable";      //增加一个自动增长的字段
       ADOX.ColumnClass col = new ADOX.ColumnClass();
       col.ParentCatalog = cat;
       col.Type=ADOX.DataTypeEnum.adInteger; // 必须先设置字段类型
       col.Name = "id";
       col.Properties["Jet OLEDB:Allow Zero Length"].Value= false;
       col.Properties["AutoIncrement"].Value= true;
       tbl.Columns.Append (col,ADOX.DataTypeEnum.adInteger,0);      //增加一个文本字段
       ADOX.ColumnClass col2 = new ADOX.ColumnClass();
       col2.ParentCatalog = cat;
       col2.Name = "Description";
       col2.Properties["Jet OLEDB:Allow Zero Length"].Value= false;
       tbl.Columns.Append (col2,ADOX.DataTypeEnum.adVarChar,25);      //设置主键
       tbl.Keys.Append("PrimaryKey",ADOX.KeyTypeEnum.adKeyPrimary,"id","","");
       cat.Tables.Append (tbl);      Response.Write("<br>数据库表:" + tbl.Name + "已经创建成功!");
       tbl=null;
       cat = null;
     }    #region Web 窗体设计器生成的代码
     override protected void OnInit(EventArgs e)
     {
       //
       // CODEGEN: 该调用是 ASP.NET Web 窗体设计器所必需的。
       //
       InitializeComponent();
       base.OnInit(e);
     }    /// <summary>
     /// 设计器支持所需的方法 - 不要使用代码编辑器修改
     /// 此方法的内容。
     /// </summary>
     private void InitializeComponent()
     {    
       this.Load += new System.EventHandler(this.Page_Load);
     }
     #endregion
   }
 }

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

昨天有位朋友问起一个问题,客户相要一个Access格式的数据,现在的情况是程序已经实现了导出Excel,问题转化成了Excel怎么样转成Access,这点实现起来相对来说比较容易,office本身就有这个功能,但问题是,从web页面导出的Excel不能很兼容的导成Access,这是一点,还有一个方面是让客户去做这个转化工作不是太好,为了提高用户体验,最好是用代码实现了。
能不能一下子转成Access出来呢?这是我一下想的的问题,如果有的话,客户就省很多力气了,但找了一些相关资料,没有找到把GridView直接导成Access的,也就是客户端比较难实现。想到这里,客户端难实现,服务端应该好实现吧,先把我数据库中的数据转化成一个access的文件,然后客户再下载下来,这个相对来说比较容易实现。
主要思路:在服务端,把一种数据中的数据,生成access文件,下载给客户商。
分步实现:
第一:创建Access文件
第二:复制数据库格式,在Access文件中创建新表
第三:复制数据到Access文件中
第四:实现下载
创建Access文件
原本创建Access文件的语法比较简单
首先引入命名空间using ADOX; 该命名空间位于Interop.ADOX.dll文件中,ADOX.CatalogClass cat = new ADOX.CatalogClass();
cat.Create(@"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=D:/Data.mdb;");
这样,就能在指定的D盘下创建一个Data.mdb的Access文件。文件是创建好了,但引来了后续的一些问题,因为我们在实现下载时,要用到Response.WriteFile(文件),此时的Response.WriteFile()要求是独立享有这个文件操作权限,但前期创建时的进程一直释放不掉(如果谁有好的方法可以告我如何释放),这里还得考虑多人操作,有可能同时有多要在创建Access文件或释放这个文件。这样就会出现运行时错误,提示该文件被其他进程独占。
为了解决这个问题,同时还涉及到防止进程的释放带来的其他问题,这里我捌了一下弯来实现,先创建一个Data.mdb存放在网站的App_Data文件夹下,后期所有客户端要下导出Access表,都在这里拷贝一份,然后对新文件进行操作。另外再新建一个DownLoad文件夹用来存用户下载的Access文件。
代码如下:
//拷贝Access数据表,不移动string newfile=DateTime .Now.ToString ("MMddhhmmss")+".mdb";
File.Copy(Server.MapPath("~") + @"/App_Data/data.mdb", Server.MapPath("~") + @"/App_Data/" + newfile);复制数据库格式,在Access文件中创建新表在这里,我是从SQL Server中生表生成Access的表,当然,可以用相关的工具完成些功能,但如果对方的数据库不是SQL Se

rver可能就不太好用了。这里选择SQL Server只是一种演示数据库。
我们知道,创建一张表有几个要素,表名,字段名,字段类型,字段大小,这里,我们得先从SQL Server中查出该表的这些要素,然后创建Access表,如果是其他数据库,就要相应的转化一下对应的数据类型格式。
代码实现如下:
在web.config中创建两个连接字符串

<add name="AccessConStr" connectionString="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DataDirectory|/data.mdb;Persist Security Info=True;" providerName="System.Data.OleDb"/>
 <add name="SqlConStr" connectionString="server=.;database=cum_data;uid=sa;pwd=sa;" providerName="System.Data.SqlClient"/>


这两个字符,一个用来连接SQL Server数据库一个用来连接我们创建的Access数据库。
接来查看导库的代码:

string SqlConstr = ConfigurationManager.ConnectionStrings["SqlConStr"].ConnectionString;
 string sql = "select column_name,data_type,character_maximum_length from information_schema.columns where table_name='kh'";
 SqlConnection con = new SqlConnection(SqlConstr);
 SqlCommand cmd = new SqlCommand(sql, con); 
 string AccSql = "";//用来组合生成Access表的SQL语句
 try
 {
 con.Open();
 SqlDataReader DR = cmd.ExecuteReader();
 while (DR.Read())
 {
 if (DR.GetValue(2).ToString() == "")
 {
 AccSql += DR.GetValue(0).ToString() + " " + DR.GetValue(1).ToString() + ",";
 }
 else
 {
 AccSql += DR.GetValue(0).ToString() + " " + DR.GetValue(1).ToString() + "(" + DR.GetValue(2).ToString() + "),";
 }
 }
 }
 catch
 { }
 finally
 {
 con.Close();
 }
 AccSql = AccSql.Substring(0, AccSql.Length - 1);
 string AccConstr = ConfigurationManager.ConnectionStrings["AccessConStr"].ConnectionString.Replace ("data.mdb",newfile );
 OleDbConnection CON = new OleDbConnection(AccConstr);
 OleDbCommand CMD = new OleDbCommand();
 CMD.Connection = CON;
 try
 {
 CON.Open();
 CMD.CommandText = "create table kh(" + AccSql + ")";
 CMD.ExecuteNonQuery();
 }
 catch
 { }
 finally
 {CON.Close();
 }


在上述代码中,SQL语句是比较关键的,“select column_name,data_type,character_maximum_length from information_schema.columns where table_name='kh'”,本SQL查询语句是从把原表的字段名,字段类型,字段大小查询出来,当然,不同的数据库,这个语句不近相同。
复制数据到Access文件中到现在,我们已创建好了数据表格式,接下来,就是要把数据导到Access中。
代码如下:

SqlDataAdapter DA = new SqlDataAdapter("select * from kh", SqlConstr);
 DataTable DT = new DataTable();
 DA.Fill(DT);
 foreach (DataRow DRR in DT.Rows)
 {
 DRR.SetAdded();
 }
 OleDbDataAdapter ODA = new OleDbDataAdapter("select * from kh", AccConstr);
 OleDbCommandBuilder cmb = new OleDbCommandBuilder(ODA);
 ODA.Update(DT);


这里用到了Adapter的一个方法,Update,可以把DataTable中RowState为Add的数据提交会数据库,这样做起来相对要省力些。
在里,要把有数据的Access文件,移动到DownLoad文件夹下File.Move(Server.MapPath("~") + @"/App_Data/"+newfile , Server.MapPath("~") + @"/DownLoad/" + newfile);
实现下载

Response.Clear();
 Response.ClearHeaders();
 Response.Charset = "utf-8";
 Response.Buffer = false ;
 this.EnableViewState = false;
 Response.ContentType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
 Response.ContentEncoding = System.Text.Encoding.UTF8;
 Response.AppendHeader("Content-Disposition", "attachment;filename=" + newfile); 
 Response.WriteFile(Server.MapPath("~") + @"/DownLoad/" + newfile ,true );
 Response.Flush();
 Response.Close();
 Response.End();


下载代码是通用的代码,这里不作说明。
整个解决方案就是把文件操作,数据操作,文件下载有机的结合在一起,实现这个用户下载Access文件的需求。
其实有时候我们去实现一个问题的时候,总体是有一定难度的,但当我们想办法,通过分解问题来实现的时候,相对来说就比较简单的实现了