先说背景,最近需要在ASP.NET网站中读取Excel文件内容,优先考虑使用Oledb的查询方式,全部逻辑完工后本机测试一切都OK,但是一旦切换用另外机器使用其它用户名登录网站就会出现数据读不出的现象。
把网站目录的权限都检查了一遍后,还是无果。真实的excel文件就生成在网站根目录的temp文件夹,并且给了这个文件夹加了everyone读写的权限。通过debug其它用户访问站点的行为时得到下面这个异常:
System.Data.OleDb.OleDbException was caught Message=Unspecified error Source=Microsoft Access Database Engine ErrorCode=-2147467259 StackTrace: at System.Data.OleDb.OleDbConnectionInternal..ctor(OleDbConnectionString constr, OleDbConnection connection) at System.Data.OleDb.OleDbConnectionFactory.CreateConnection(DbConnectionOptions options, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningObject) at System.Data.ProviderBase.DbConnectionFactory.CreateNonPooledConnection(DbConnection owningConnection, DbConnectionPoolGroup poolGroup) at System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection) at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory) at System.Data.OleDb.OleDbConnection.Open() at System.Data.Common.DbDataAdapter.QuietOpen(IDbConnection connection, ConnectionState& originalState) at System.Data.Common.DbDataAdapter.FillInternal(DataSet dataset, DataTable[] datatables, Int32 startRecord, Int32 maxRecords, String srcTable, IDbCommand command, CommandBehavior behavior) at System.Data.Common.DbDataAdapter.Fill(DataSet dataSet, Int32 startRecord, Int32 maxRecords, String srcTable, IDbCommand command, CommandBehavior behavior) at System.Data.Common.DbDataAdapter.Fill(DataSet dataSet)
接下来就是痛苦的google和bing,但是几个小时下来发现自己遇到的情况还是和别人描述的不一样,错误依旧。但是有一点是可以确定的,至少我遇到的情况不是Oledb的组件没安装的问题,因为本机的管理员账户是可以正常访问页面并读出数据的,但是换了别的用户就不可以,那么问题一定是权限的问题。尝试了IIS里相关的权限配置,依然无果。
最后在万般无奈下到摆渡里搜“Microsoft Access Database Engine IIS7”,没想到真有我想要的结果:
因为MS Jet引擎改变了临时目录的位置,但是又没有对临时的存取权限,导致数据库使用失败。
给“系统盘:/Windows/ServiceProfiles/NetworkService/AppData/Local/Temp”目录添加 一个“Authenticated Users”的用户,其中AppData目录是隐藏的,在进入的时候可以直接在地址栏输入路径,或者在文件夹选项里显示隐藏文件。该项尤其重要,不设置则一直提示microsoft jet database engine 80004005 错误。
设置权限步骤:右击Temp文件夹,选择“属性”》选择“安全”选项卡》单击“编辑”》出来“Temp 的权限”对话框,单击“添加”,在下面的“输入对象名称来选择”中输入Authenticated Users,确定》返回到“Temp 的权限”,将Authenticated Users的权限中的完全控制给勾上,确定》确定。
附上查询Excel文件的代码段:
/// <summary> /// Queries the data. /// </summary> /// <param name="filepath">The Excel file path.</param> /// <param name="sheetName">Name of the sheet.</param> /// <returns></returns> private static DataSet QueryData(string filepath, string sheetName) { DataSet ds = new DataSet(); if (File.Exists(filepath)) { string sqlcmd = string.Format("select * from [{0}$]", sheetName); string conStr = string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties='Excel 12.0 Xml;HDR=YES';", filepath); OleDbDataAdapter da = new OleDbDataAdapter(sqlcmd, conStr); da.Fill(ds); } return ds; } }