Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/325.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# System.Data.IDB命令和异步执行?_C#_Sql_Interface_Asynchronous_Sqlclient - Fatal编程技术网

C# System.Data.IDB命令和异步执行?

C# System.Data.IDB命令和异步执行?,c#,sql,interface,asynchronous,sqlclient,C#,Sql,Interface,Asynchronous,Sqlclient,System.Data.SqlClient.SqlCommand 有办法 BeginExecuteNonQuery BeginExecuteReader BeginExecuteXmlReader 及 用于异步执行 System.Data.idb命令 只有 仅用于同步操作 有异步操作的接口吗? 此外,为什么没有BeginExecuteCalar?不,它们没有接口 之所以没有一个BeginExecuteCalar是因为您可能不需要异步调用就可以很快地返回一个值您可以通过自定义代码实现异步行为,因

System.Data.SqlClient.SqlCommand 有办法

BeginExecuteNonQuery
BeginExecuteReader
BeginExecuteXmlReader

用于异步执行

System.Data.idb命令 只有

仅用于同步操作

有异步操作的接口吗?

此外,为什么没有BeginExecuteCalar?

不,它们没有接口


之所以没有一个
BeginExecuteCalar
是因为您可能不需要异步调用就可以很快地返回一个值

您可以通过自定义代码实现异步行为,因为它并不复杂,至于你的问题-你的目标没有任何标准的异步操作。

事实上,创建相当于BeginExecutenQuery、EndExecutenQuery等的异步行为将是一项相当困难的任务。这些API的实现远远优于简单地生成一个单独的线程,等待数据库响应并调用回调。它们依赖于I/O重叠,并提供更好的线程经济性。在网络跳转、命令的数据库处理期间,不会消耗额外的线程,这可能是整个调用时间的99%。对于一些调用来说,这没有什么区别,但是当您设计一个高吞吐量服务器时,线程经济性变得非常重要

我在想为什么BeginExecuteCalar不见了。另外,大多数其他的提供者,例如ODP.Net,根本没有异步API


是的,没有异步操作的接口

即使您正在检索“一个值”,大多数时间也会花在1)网络跳到数据库服务器上,2)数据库服务器执行命令上。比您将花费更多的时间,比如说,将1000条记录读入数据集中。所以,我同意,不清楚为什么没有BeginExecuteScalar

为了准确地解决这个问题,我构建了一个垫片,如果IDbConnection.IDbCommand/IDataReader上存在异步方法,则调用它们;如果不存在,则调用常规方法

资料来源:

努吉:

例如:

        using (IDbConnection connection = new SqlConnection(connectionString))
        {
            await connection.OpenAsync();

            IDbCommand command = connection.CreateCommand();
            command.CommandText = "SELECT Name FROM Person;";
            using (IDataReader reader = await command.ExecuteReaderAsync())
            {
                do
                {
                    while (await reader.ReadAsync())
                    {
                        if (!await reader.IsDBNullAsync(0))
                        {
                            var name = reader.GetFieldValueAsync<string>(0);
                            Assert.IsNotNull(name);
                        }
                    }
                } while (await reader.NextResultAsync());
            }
        }
使用(IDbConnection连接=新的SqlConnection(connectionString))
{
等待连接。OpenAsync();
IDbCommand=connection.CreateCommand();
command.CommandText=“从人员中选择姓名;”;
使用(IDataReader reader=await command.ExecuteReaderAsync())
{
做
{
while(等待reader.ReadAsync())
{
如果(!wait reader.IsDBNullAsync(0))
{
var name=reader.GetFieldValueAsync(0);
Assert.IsNotNull(名称);
}
}
}while(等待reader.NextResultAsync());
}
}

IDbCommand
没有begin/end异步方法,因为它们在ADO.NET的原始.NET 1.1版本中还不存在,当异步方法存在时,将它们添加到
IDbCommand
(向接口添加成员对于该接口的实现者来说是一个突破性的更改)


我不知道为什么
BeginExecuteScalar
不存在,但它可以作为一种扩展方法来实现,它围绕
beginexecuterader
展开。无论如何,在.NET 4.5中,我们现在有了更容易使用的
ExecuteScalarAsync

当我需要将数据调用迁移到异步方法时,我偶然发现了这个问题。我已经为未来的.NET标准创建了一个问题。同时,我还创建了。

我建议在使用数据库API时,将
DbCommand
及其朋友视为接口。为了将API推广到各种数据库提供程序上,
DbCommand
IDbCommand
一样好,或者可以说更好,因为它包括较新的技术,例如适当的
wait
able
Task
*Async()
成员

MS无法将任何具有新功能的新方法添加到
IDbCommand
。如果他们要向
IDbCommand
添加一个方法,这将是一个突破性的变化,因为任何人都可以在他们的代码中自由地实现该接口,而微软在维护框架中的ABI和API兼容性方面付出了很多努力。如果他们在.net版本中扩展了接口,以前有效的客户代码将停止编译,未重新编译的现有程序集将开始遇到运行时错误。此外,他们无法通过扩展方法添加适当的
*Async()
Begin*()
方法,而不在幕后对
DbCommand
执行难看的强制转换(这本身就是一种糟糕的做法,破坏了类型安全性,不必要地引入动态运行时强制转换)

另一方面,MS可以在不破坏ABI的情况下向
DbCommand
添加新的虚拟方法。向基类添加新方法可能会被视为破坏API(编译时,破坏不如运行时糟糕),因为如果您继承了
DbCommand
,并添加了同名的成员,您将开始收到警告)。因此,
DbCommand
可以获得新功能,对使用遵循良好实践的代码的影响最小(例如,只要它不与类型系统和使用类似
myCommand.GetType().GetMethods()[3].Invoke(myCommand,…)
的调用方法兼容,大多数东西都会继续工作)

MS可以用来支持喜欢界面的人的一个可能策略是引入新的界面,其名称为
IAsyncDbCommand
,并让
DbCommand
实现它们。他们没有这样做。我不知道为什么,但他们可能没有这样做,因为这会增加复杂性和直接治疗的选择
ExecuteNonQuery
ExecuteReader
ExecuteXmlReader
        using (IDbConnection connection = new SqlConnection(connectionString))
        {
            await connection.OpenAsync();

            IDbCommand command = connection.CreateCommand();
            command.CommandText = "SELECT Name FROM Person;";
            using (IDataReader reader = await command.ExecuteReaderAsync())
            {
                do
                {
                    while (await reader.ReadAsync())
                    {
                        if (!await reader.IsDBNullAsync(0))
                        {
                            var name = reader.GetFieldValueAsync<string>(0);
                            Assert.IsNotNull(name);
                        }
                    }
                } while (await reader.NextResultAsync());
            }
        }