带有 using 关键字的 SqlDataAdapter

Posted

技术标签:

【中文标题】带有 using 关键字的 SqlDataAdapter【英文标题】:SqlDataAdapter with using keyword 【发布时间】:2013-03-11 07:45:57 【问题描述】:

下面的代码健康吗?或者我不需要使用using 关键字,因为SqlDataAdapter 将处理关闭连接?

public static DataSet Fetch(string sp, SqlParameter [] prm)

    using (SqlConnection con = new SqlConnection(ConStr))
    
        using (SqlCommand cmd = con.CreateCommand())
        
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.CommandText = sp;
            cmd.Parameters.AddRange(prm);

            using (SqlDataAdapter dta = new SqlDataAdapter(cmd))
            
                DataSet dst = new DataSet();
                dta.Fill(dst);

                return dst;
            
        
    



@MarkGravell 我在这里需要一个建议,我真的很想使用DataReader,但我一直在寻找使用using 关键字来确保关闭连接。对于DataReader,我们不能使用它,因为如果我们想将DataReader 返回到某个方法,它将关闭连接。 那么,您认为以下技术适用于 DataReaderusing 关键字:

public static SqlDataReader Fetch(string sp, SqlParameter [] prm)

    SqlCommand cmd = new SqlConnection(ConStr).CreateCommand();
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.CommandText = sp;
    cmd.Parameters.AddRange(prm);
    cmd.Connection.Open();

    return cmd.ExecuteReader(CommandBehavior.CloseConnection);


using (SqlDataReader dtrPrize = Sql.Fetch("SelectPrize", new SqlParameter[]  new SqlParameter("id", id) ))

    dtrPrize.Read();

    Prize prize = new Prize();
    prize.id = (int)dtrPrize[dtrPrize.GetOrdinal("id")];
    prize.artitle = (string)dtrPrize[dtrPrize.GetOrdinal("artitle")];
    prize.entitle = (string)dtrPrize[dtrPrize.GetOrdinal("entitle")];
    prize.ardetail = (string)dtrPrize[dtrPrize.GetOrdinal("ardetail")];
    prize.endetail = (string)dtrPrize[dtrPrize.GetOrdinal("endetail")];
    prize.image = (string)dtrPrize[dtrPrize.GetOrdinal("image")];
    prize.theme = (string)dtrPrize[dtrPrize.GetOrdinal("theme")];
    prize.price = (int)dtrPrize[dtrPrize.GetOrdinal("price")];
    prize.audience = (int)dtrPrize[dtrPrize.GetOrdinal("audience")];
    prize.type = (byte)dtrPrize[dtrPrize.GetOrdinal("type")];
    prize.status = (byte)dtrPrize[dtrPrize.GetOrdinal("status")];
    prize.voucher = (string)dtrPrize[dtrPrize.GetOrdinal("voucher")];
    prize.supplierid = (int)dtrPrize[dtrPrize.GetOrdinal("supplierid")];
    prize.created = (DateTime)dtrPrize[dtrPrize.GetOrdinal("created")];
    prize.updated = (DateTime)dtrPrize[dtrPrize.GetOrdinal("updated")];

    return prize;

【问题讨论】:

代码没问题。 Connection 将在 DataAdapter.Fill 中隐式打开/关闭。 【参考方案1】:

健康的;就我个人而言,我认为不健康的一点是它使用了DataSetDataAdapter,但这可能只是我个人的偏见。

是的,您应该在此处处理适配器等(这显然是 using 为您所做的)。

作为一个琐碎无意义的整理,您可以堆叠usings - 只是让它不那么冗长:

using (SqlConnection con = new SqlConnection(ConStr))
using (SqlCommand cmd = con.CreateCommand())

【讨论】:

@MarkGravell 你能解释一下,为什么还要处理适配器? SqlConnection 配置不够? @voo 因为它实现了IDisposable,我们已经完成了它。这就是足够的理由。除此之外的任何事情都将进入实施细节,我们应该避免。作为消费者,它需要归结为:“它是否实现了IDisposable?我完成了吗?” @MarkGravell 正如您提到的 DataAdapter 和 DataSet 可能不健康,您的意思是使用 DataReader 更好,将其映射到对象,关闭连接并最终返回模型对象而不是返回 DataSet ?你在这里有什么建议? @user2155873 我确实在这里强烈地引导向常规对象模型(而不是 DataSet)。你如何与之交互取决于你:有无数的 ORM 工具可用。就我个人而言,我使用了很多“精致”,但这可能只是个人偏见。【参考方案2】:

只留下第一个using(连接上的那个)就足够了,因为处理连接将处理您需要处理的所有内容。

但是,处理所有内容并没有什么坏处,只是多一些代码。

【讨论】:

以上是关于带有 using 关键字的 SqlDataAdapter的主要内容,如果未能解决你的问题,请参考以下文章

PHP“使用”关键字和自动加载

为啥使用带有 SqlTransaction 的 using 语句?

c# 中using 关键字有哪些用法?

使用带有 N 查询的“USING”子句的雄辩连接

Rust 有问有答之 use 关键字

Rust 有问有答之 use 关键字