The issue is that VS2010 Code Analysis is returning two CA2000 warnings for a particular function. I haven't been successful at reproducing the warnings with a smaller block of code, so I've posted the original function in it's entirety.
public int SaveTransaction( Transaction tx, UserAccount account ) {
        if ( tx == null ) {
            throw new ArgumentNullException( "tx" );
        }
        if ( account == null ) {
            throw new ArgumentNullException( "account" );
        }
        bool isRefund = tx.TransactionType == LevelUpTransaction.TransactionTypes.Refund;
        int pnRef = 0;
        using ( SqlConnection conn = new SqlConnection( DatabaseConfiguration.ConnectionString ) ) {
            using ( SqlCommand cmd = new SqlCommand( "dbo.SaveTransaction", conn ) ) {
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.Parameters.Add( "@InvoiceId", SqlDbType.VarChar, 100 ).Value = tx.InvoiceNumber;
                cmd.Parameters.Add( "@TxStartDate", SqlDbType.DateTime ).Value = tx.TransactionBeginDate;
                cmd.Parameters.Add( "@AuthDate", SqlDbType.DateTime ).Value = tx.AuthenticationDate;
                cmd.Parameters.Add( "@MerchantKey", SqlDbType.Int ).Value = account.MerchantKey;
                cmd.Parameters.Add( "@UserName", SqlDbType.Char, 25 ).Value = account.UserName;
                cmd.Parameters.Add( "@RegisterNumber", SqlDbType.Char, 10 ).Value = tx.RegisterNumber;
                cmd.Parameters.Add( "@ResellerKey", SqlDbType.Int ).Value = account.ResellerKey;
                cmd.Parameters.Add( "@TxEndDate", SqlDbType.DateTime ).Value = tx.TransactionEndDate;
                cmd.Parameters.Add( "@IpAddress", SqlDbType.VarChar, 15 ).Value = account.IPAddress;
                cmd.Parameters.Add( "@CustomerId", SqlDbType.VarChar, 50 ).Value = tx.CustomerId;
                cmd.Parameters.Add( "@TransactionId", SqlDbType.VarChar, 50 ).Value = tx.TransactionId;
                cmd.Parameters.Add( "@ProcStartDate", SqlDbType.DateTime ).Value = tx.ProcessorBeginDate;
                cmd.Parameters.Add( "@ProcEndDate", SqlDbType.DateTime ).Value = tx.ProcessorEndDate;
                cmd.Parameters.Add( "@AuthAmount", SqlDbType.Money ).Value = StringParser.ParseDecimal( tx.OriginalAmount );
                cmd.Parameters.Add( "@ResultCode", SqlDbType.VarChar, 50 ).Value = tx.ResultCode;
                cmd.Parameters.Add( "@ResultMessage", SqlDbType.VarChar, 150 ).Value = tx.ResultMessage;
                cmd.Parameters.Add( "@PONumber", SqlDbType.VarChar, 100 ).Value = tx.PurchaseOrderNumber;
                cmd.Parameters.Add( "@TaxAmount", SqlDbType.Money ).Value = StringParser.ParseDecimal( tx.TaxAmount );
                cmd.Parameters.Add( "@Refund", SqlDbType.Bit ).Value = isRefund;
                if ( tx.Order != null ) {
                    cmd.Parameters.Add( "@HostDate", SqlDbType.VarChar, 50 ).Value = tx.Order.HostTime.ToString();
                    cmd.Parameters.Add( "@ApprovalCode", SqlDbType.VarChar, 50 ).Value = tx.Order.TransactionId.ToString( CultureInfo.InvariantCulture );
                    cmd.Parameters.Add( "@NameOnCard", SqlDbType.VarChar, 200 ).Value = tx.Order.UserFirstName + " " + tx.Order.UserLastNameInitial;
                    cmd.Parameters.Add( "@TipAmount", SqlDbType.Money ).Value = StringParser.ParseDecimal( tx.Order.Tip.FormattedAmount );
                    cmd.Parameters.Add( "@TotalAmount", SqlDbType.Money ).Value = StringParser.ParseDecimal( tx.Order.TotalAmount.FormattedAmount );
                    cmd.Parameters.Add( "@DiscountAmount", SqlDbType.Money ).Value = StringParser.ParseDecimal( tx.Order.CreditAmount.FormattedAmount );
                }
                else  {
                    cmd.Parameters.Add( "@NameOnCard", SqlDbType.VarChar, 200 ).Value = DBNull.Value;
                    cmd.Parameters.Add( "@HostDate", SqlDbType.VarChar, 50 ).Value = DBNull.Value;
                    cmd.Parameters.Add( "@ApprovalCode", SqlDbType.VarChar, 50 ).Value = DBNull.Value;
                    cmd.Parameters.Add( "@TipAmount", SqlDbType.Money ).Value = 0;
                    cmd.Parameters.Add( "@TotalAmount", SqlDbType.Money ).Value = 0;
                    cmd.Parameters.Add( "@DiscountAmount", SqlDbType.Money ).Value = 0;
                }
                if ( isRefund ) {
                    cmd.Parameters.Add( "@OriginalPnRef", SqlDbType.Int ).Value = tx.OriginalToken;
                }
                conn.Open();
                using ( SqlDataReader dr = cmd.ExecuteReader() ) {
                    while ( dr.Read() ) {
                        pnRef = SqlNull.Integer( dr["TRX_HD_Key"] );
                    }
                }
            }
        }
        return pnRef;
    }
The two CA2000 warnings pertain to the using statements containing the SqlConnection and SqlCommand.
I can't find any issues in the code itself, but I have found that commenting out lines at random will make the errors go away.  For instance, commenting out the three money fields being set to 0 in the else block will remove the warnings.  Conversely, commenting out just the three lines with DBNull.Value at the end will remove the error too.  I can't make sense of the results.
This has been reported on Microsoft Connect as a possible bug in the analyzer.  Apparently, if a using statement contains a lot of code this message is reported erroneously.
It can be suppressed with:
[System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Reliability", "CA2000:Dispose objects before losing scope" )]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With