“((System.Data.SqlClient.SqlConnection)(_connection)).ServerVersion”引发了“System.InvalidOperationException”类型的异常
求指导
利用工厂模式的项目
SqlProvider类代码:
1 /// <summary> 2 /// 提供数据库访问的相关方法,无法继承此类。 3 /// </summary> 4 public sealed class SqlProvider : IDbProvider 5 { 6 7 #region Fields... 8 9 /// <summary> 10 /// 数据库连接字符串。 11 /// </summary> 12 private string _connectionstring = null; 13 /// <summary> 14 /// 数据库连接。 15 /// </summary> 16 private IDbConnection _connection = null; 17 /// <summary> 18 /// 数据库事务。 19 /// </summary> 20 private IDbTransaction _transaction = null; 21 /// <summary> 22 /// 数据阅读器。 23 /// </summary> 24 private IDbDataAdapter _dataAdapeter = null; 25 /// <summary> 26 /// 数据库命令。 27 /// </summary> 28 private IDbCommand _command = null; 29 /// <summary> 30 /// 查询次数统计。 31 /// </summary> 32 private int _queryCount = 0; 33 34 #endregion 35 36 #region Properties... 37 38 /// <summary> 39 /// 数据库连接字符串。 40 /// </summary> 41 public string ConnectionString 42 { 43 get 44 { 45 if (_connectionstring == null) 46 { 47 _connectionstring = "Data Source=192.168.25.11;User ID=test;Password=123456;Initial Catalog=test;Pooling=true"; 48 } 49 return _connectionstring; 50 } 51 } 52 53 /// <summary> 54 /// 查询次数。 55 /// </summary> 56 public int QueryCount 57 { 58 get { return _queryCount; } 59 } 60 61 /// <summary> 62 /// 取得数据库连接。 63 /// </summary> 64 public IDbConnection Connection 65 { 66 get 67 { 68 if (_connection == null) 69 { 70 _connection = new SqlConnection(ConnectionString); 71 } 72 return _connection; 73 } 74 } 75 76 /// <summary> 77 /// 取得数据库命令。 78 /// </summary> 79 public IDbCommand Command 80 { 81 get 82 { 83 if (_command == null) 84 { 85 _command = new SqlCommand(); 86 _command.Connection = _connection; 87 } 88 return _command; 89 } 90 } 91 92 /// <summary> 93 /// 取得 DataAdapter 。 94 /// </summary> 95 public IDbDataAdapter DataAdapter 96 { 97 get 98 { 99 if (_dataAdapeter == null) 100 { 101 _dataAdapeter = new SqlDataAdapter(Command as SqlCommand); 102 } 103 return _dataAdapeter; 104 } 105 } 106 107 /// <summary> 108 /// 获取是否执行了事务操作。 109 /// </summary> 110 public bool IsInTracsaction 111 { 112 get 113 { 114 return _transaction != null; 115 } 116 } 117 118 #endregion 119 120 #region Constructors... 121 122 /// <summary> 123 /// 初始化 <see cref="SqlProvider"/> 类的新实例。 124 /// </summary> 125 public SqlProvider() 126 { 127 128 } 129 130 #endregion 131 132 #region Methods... 133 134 /// <summary> 135 /// 增加查询次数。 136 /// </summary> 137 public void AddQuery() 138 { 139 _queryCount++; 140 } 141 142 /// <summary> 143 /// 打开数据库连接。 144 /// </summary> 145 public void Open() 146 { 147 Connection.Open(); 148 } 149 150 /// <summary> 151 /// 关闭数据库连接。 152 /// </summary> 153 public void Close() 154 { 155 if (_connection != null) 156 Connection.Close(); 157 } 158 159 /// <summary> 160 /// 检索 SQL 参数信息并填充。 161 /// </summary> 162 /// <param name="cmd"></param> 163 public void DeriveParameters(IDbCommand cmd) 164 { 165 if ((cmd as SqlCommand) != null) 166 { 167 SqlCommandBuilder.DeriveParameters(cmd as SqlCommand); 168 } 169 } 170 171 /// <summary> 172 /// 生成数据库参数。 173 /// </summary> 174 /// <param name="ParamName">参数名。</param> 175 /// <param name="DbType">参数类型。</param> 176 /// <param name="Size">参数大小。</param> 177 /// <returns>返回生成的参数。</returns> 178 public IDataParameter MakeParam(string ParamName, DbType DbType, int Size) 179 { 180 SqlParameter param; 181 182 if (Size > 0) 183 param = new SqlParameter(ParamName, DataTypeConvert.Convert(DbType), Size); 184 else 185 param = new SqlParameter(ParamName, DataTypeConvert.Convert(DbType)); 186 187 return param; 188 } 189 190 /// <summary> 191 /// 是否支持全文搜索。 192 /// </summary> 193 /// <returns></returns> 194 public bool IsFullTextSearchEnabled() 195 { 196 return true; 197 } 198 199 /// <summary> 200 /// 是否支持压缩数据库。 201 /// </summary> 202 /// <returns></returns> 203 public bool IsCompactDatabase() 204 { 205 return true; 206 } 207 208 /// <summary> 209 /// 是否支持备份数据库。 210 /// </summary> 211 /// <returns></returns> 212 public bool IsBackupDatabase() 213 { 214 return true; 215 } 216 217 /// <summary> 218 /// 返回最后插入记录的自增ID值, 如不支持则为""。 219 /// </summary> 220 /// <returns></returns> 221 public string GetLastIdSql() 222 { 223 return "SELECT SCOPE_IDENTITY()"; 224 } 225 226 /// <summary> 227 /// 是否支持数据库优化。 228 /// </summary> 229 /// <returns></returns> 230 public bool IsDbOptimize() 231 { 232 return true; 233 } 234 235 /// <summary> 236 /// 是否支持数据库收缩。 237 /// </summary> 238 /// <returns></returns> 239 public bool IsShrinkData() 240 { 241 return true; 242 } 243 244 /// <summary> 245 /// 是否支持存储过程。 246 /// </summary> 247 /// <returns></returns> 248 public bool IsStoreProc() 249 { 250 return true; 251 } 252 253 /// <summary> 254 /// 开始执行数据库事务。 255 /// </summary> 256 public void BeginTransaction() 257 { 258 _transaction = Connection.BeginTransaction(); 259 Command.Transaction = _transaction; 260 } 261 262 /// <summary> 263 /// 以指定的数据事务锁执行数据库事务。 264 /// </summary> 265 /// <param name="level"></param> 266 public void BeginTransaction(IsolationLevel level) 267 { 268 _transaction = Connection.BeginTransaction(level); 269 Command.Transaction = _transaction; 270 } 271 272 /// <summary> 273 /// 提交数据库事务。 274 /// </summary> 275 public void Commit() 276 { 277 if (_transaction == null) 278 throw new Exception("No transaction can Commit."); 279 _transaction.Commit(); 280 _transaction.Dispose(); 281 _transaction = null; 282 _command.Transaction = null; 283 } 284 285 /// <summary> 286 /// 回滚数据库事务。 287 /// </summary> 288 public void Rollback() 289 { 290 if (_transaction == null) 291 throw new Exception("No transaction can Rollback."); 292 _transaction.Rollback(); 293 _transaction.Dispose(); 294 _transaction = null; 295 _command.Transaction = null; 296 } 297 298 /// <summary> 299 /// 释放资源。 300 /// </summary> 301 public void Dispose() 302 { 303 Close(); 304 if (_command != null) 305 _command.Dispose(); 306 if (_connection != null) 307 _connection.Dispose(); 308 _connectionstring = null; 309 _connection = null; 310 _command = null; 311 _dataAdapeter = null; 312 _transaction = null; 313 } 314 315 #region Instance 316 317 /// <summary> 318 /// 创建新的数据访问程序实例。 319 /// </summary> 320 /// <returns>返回数据访问程序实例。</returns> 321 public IDbProvider CreateInstance() 322 { 323 return new SqlProvider(); 324 } 325 326 #endregion 327 328 #endregion 329 330 }
SqlFactory类代码:
1 /// <summary> 2 /// 数据访问抽象工厂模型。 3 /// </summary> 4 public sealed class SqlFactory : IFactory 5 { 6 private static IDatabase _database = null; 7 private static IDbArchive _archive = null; 8 private static IDbArticle _article = null; 9 private static IDbCategory _category = null; 10 private static IDbComment _comment = null; 11 private static IDbSetting _setting = null; 12 private static IDbNotice _notice = null; 13 private static IDbAdvertising _advertising = null; 14 private static IDbAttachment _attachment = null; 15 private static IDbLog _log = null; 16 private static IDbSlideshow _slideshow = null; 17 private static IDbTag _tag = null; 18 private static IDbTrackBack _trackback = null; 19 private static IDbMember _member = null; 20 private static IDbStatistic _statistic = null; 21 private static IDbFriendLink _friendlink = null; 22 23 /// <summary> 24 /// 创建数据访问程序实例。 25 /// </summary> 26 /// <returns></returns> 27 public IDbProvider CreateDbProvider() 28 { 29 return new SqlProvider(); 30 } 31 32 public IDatabase Database 33 { 34 get 35 { 36 if (_database == null) 37 _database = new SqlDatabase(); 38 return _database; 39 } 40 } 41 42 public IDbArticle Article 43 { 44 get 45 { 46 if (_article == null) 47 _article = new DbArticle(); 48 return _article; 49 } 50 } 51 52 public IDbArchive Archive 53 { 54 get 55 { 56 if (_archive == null) 57 _archive = new DbArchive(); 58 return _archive; 59 } 60 } 61 62 public IDbAttachment Attachment 63 { 64 get 65 { 66 if (_attachment == null) 67 _attachment = new DbAttachment(); 68 return _attachment; 69 } 70 } 71 72 public IDbCategory Category 73 { 74 get 75 { 76 if (_category == null) 77 _category = new DbCategory(); 78 return _category; 79 } 80 } 81 82 public IDbComment Comment 83 { 84 get 85 { 86 if (_comment == null) 87 _comment = new DbComment(); 88 return _comment; 89 } 90 } 91 92 public IDbSetting Setting 93 { 94 get 95 { 96 if (_setting == null) 97 _setting = new DbSetting(); 98 return _setting; 99 } 100 } 101 102 public IDbFriendLink FriendLink 103 { 104 get 105 { 106 if (_friendlink == null) 107 _friendlink = new DbFriendLink(); 108 return _friendlink; 109 } 110 } 111 112 public IDbNotice Notice 113 { 114 get 115 { 116 if (_notice == null) 117 _notice = new DbNotice(); 118 return _notice; 119 } 120 } 121 122 public IDbLog Log 123 { 124 get 125 { 126 if (_log == null) 127 _log = new DbLog(); 128 return _log; 129 } 130 } 131 132 public IDbTag Tag 133 { 134 get 135 { 136 if (_tag == null) 137 _tag = new DbTag(); 138 return _tag; 139 } 140 } 141 142 public IDbSlideshow Slideshow 143 { 144 get 145 { 146 if (_slideshow == null) 147 _slideshow = new DbSlideshow(); 148 return _slideshow; 149 } 150 } 151 152 public IDbStatistic Statistic 153 { 154 get 155 { 156 if (_statistic == null) 157 _statistic = new DbStatistic(); 158 return _statistic; 159 } 160 } 161 162 public IDbMember Member 163 { 164 get 165 { 166 if (_member == null) 167 _member = new DbMember(); 168 return _member; 169 } 170 } 171 172 public IDbTrackBack TrackBack 173 { 174 get 175 { 176 if (_trackback == null) 177 _trackback = new DbTrackBack(); 178 return _trackback; 179 } 180 } 181 }
我把代码复制到另一个测试项目只保留一个数据访问接口,就没有这个问题了。
麻烦你下次把异常贴出来,就算不想给我们看,你自己是否也应该先把异常的信息读一遍,我猜测是因为连接没有打开的问题,从你的截图中我看到了 State = Closed ,而要查看 ServerVersion ,连接首先必须是 Open 状态。
事实,你把异常的描述信息读一遍,你应该会看到:“无效的操作,连接已经关闭”,或者“Invalid operation.The connection is closed.”。
仅仅是简单的把异常认真的看一下,你就不需要提这个问题,何苦浪费这个时间呢?
您确定您看懂了吗?我的连接还没打开呢,肯定是关闭的。
@Charles Zhang:
"从你的截图中我看到了 State = Closed" ---〉这句话同你的“我的连接还没打开呢,肯定是关闭的”不是一个意思?
“而要查看 ServerVersion ,连接首先必须是 Open 状态。” ——你没读懂这句话的意思?
@Launcher: 您说的是对的以前没注意Open之前ServerVersion的状态,不过问题还没解决。
@Charles Zhang: 解决的办法很简单,就是在调用 ServerVersion 之前,先打开连接。你就算是直接使用 SqlConnection,如下:
SqlConnection conn = new SqlConnection();
string ver = conn.ServerVersion;
它还是会有异常,这里的问题在于你需要把握住调用的时机。所以,你应该整理下你的思路,弄明白你为什么需要在连接没有打开时就需要查看 ServerVersion 属性。如果是你的设计使然,那么你需要将调用代码 catch 住,允许调用失败;如果不是,那你需要修改你的逻辑,保证在调用前连接是已经打开的。
另外,ADO.NET 拥有完成的使用工厂模式、抽象工厂模式实现的通用数据库访问组件,不知道你为何需要自己编写。关于这方面的扩展,你可以学习一下 Enterprise Library(http://msdn.microsoft.com/en-us/library/ff648951.aspx),它其中的 Data Access Application Block 组件拥有完整的如何使用 ADO.NET 的工厂组件、抽象工厂组件实现通用数据库访问组件的功能,包括异构数据库支持、异步数据访问和同步数据访问。
@Launcher: 我主要是想实现数据查询次数等操作,企业类库我用过Microsoft.Practices.EnterpriseLibrary.Data.dll 的类库下 DataBase 类的相关方法,抽象工厂组件还没用过
@Charles Zhang: http://msdn.microsoft.com/zh-cn/library/vstudio/7h2ahss8(v=vs.100).aspx
Sql Server 的 ADO.NET 已经具有统计功能,可以直接使用。ADO.NET 中其它类型数据库的暂时不支持。
@Launcher: 好的,谢谢你了
@Charles Zhang: 问题搞定了,改成IIS就没问题了,原来是用IIS Express绑定的网站,我怀疑是网站应用程序池的问题。