本文共 2365 字,大约阅读时间需要 7 分钟。
1: class Program
2: {
3: static void Main()
4: {
5:
6: string invalidSql = "SELECT * FROM {InvalidTable}";
7: string validSql = "SELECT * FROM {ValidTable}";
8:
9:
10: Database db = DatabaseFactory.CreateDatabase();
11: using (TransactionScope scope = new TransactionScope())
12: {
13: DbCommand commandWithInvalidSql = db.GetSqlStringCommand(invalidSql);
14: DbCommand commandWithValidSql = db.GetSqlStringCommand(validSql);
15:
16: try
17: {
18: db.ExecuteReader(commandWithInvalidSql);
19: }
20: catch
21: { }
22:
23: db.ExecuteReader(commandWithValidSql);
24: }
25: }
26: }
但是在执行第二个ExecuteReader方法的时候却抛出如下一个InvalidOperationException(如下图),错误消息为:“ExecuteReader requires an open and available Connection. The connection's current state is closed.”
原因出在这里:在ExecuteReader中,相应的ADO.NET代码放在try|catch中,当异常抛出后,相应的DbConnect会被关闭。但是由于在我的代码中,两次ExecuteReader的调用是在一个相同的Ambient Transaction中执行的,DAAB在内部采用相同的DbTransaction执行这两项操作,当执行第一项操作时,由于出现异常导致DbConnect关闭,使用相同DbConnect的第二项操作肯定会失败。
1: public virtual IDataReader ExecuteReader(DbCommand command)
2: {
3: ConnectionWrapper wrapper = GetOpenConnection(false);
4:
5: try
6: {
7: //
8: // JS-L: I moved the PrepareCommand inside the try because it can fail.
9: //
10: PrepareCommand(command, wrapper.Connection);
11:
12: //
13: // If there is a current transaction, we'll be using a shared connection, so we don't
14: // want to close the connection when we're done with the reader.
15: //
16: if (Transaction.Current != null)
17: return DoExecuteReader(command, CommandBehavior.Default);
18: else
19: return DoExecuteReader(command, CommandBehavior.CloseConnection);
20: }
21: catch
22: {
23: wrapper.Connection.Close();
24: throw;
25: }
26: }
27:
我不清楚微软在设计的时候,是因为没有考虑到这种场景呢,还是不得以而为之,或者是出于其他因素的考虑,大家有何见解。