c# - Azure 表中的异步插入

标签 c# asynchronous azure azure-table-storage

如何将实体异步保存到 Windows Azure 表服务?

下面的代码同步工作,但在尝试异步保存时引发异常。

此声明:

context.BeginSaveChangesWithRetries(SaveChangesOptions.Batch,
    (asyncResult => context.EndSaveChanges(asyncResult)), null);

导致 System.ArgumentException:“当前对象未产生异步结果。参数名称:asyncResult”。

此外,异步保存时创建服务上下文的正确模式是什么?我应该为每个写操作创建一个单独的上下文吗?是否太贵(例如需要通过网络调用)?

TableStorageWriter.cs:

using System;
using System.Data.Services.Client;
using System.Diagnostics;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.StorageClient;

namespace WorkerRole1
{
    public class TableStorageWriter
    {
        private const string _tableName = "StorageTest";
        private readonly CloudStorageAccount _storageAccount;
        private CloudTableClient _tableClient;

        public TableStorageWriter()
        {
            _storageAccount = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("StorageConnectionString"));
            _tableClient = _storageAccount.CreateCloudTableClient();
            _tableClient.CreateTableIfNotExist(_tableName);
        }

        public void Write(string message)
        {
            try
            {
                DateTime now = DateTime.UtcNow;
                var entity = new StorageTestEntity
                    {
                        Message = message,
                        PartitionKey = string.Format("{0:yyyy-MM-dd}", now),
                        RowKey = string.Format("{0:HH:mm:ss.fff}-{1}", now, Guid.NewGuid())
                    };

                // Should I get this context before each write? It is efficient?
                TableServiceContext context = _tableClient.GetDataServiceContext();

                context.AddObject(_tableName, entity);

                // This statement works but it's synchronous
                context.SaveChangesWithRetries();

                // This attempt at saving asynchronously results in System.ArgumentException:
                // The current object did not originate the async result. Parameter name: asyncResult
                // context.BeginSaveChangesWithRetries(SaveChangesOptions.Batch,
                //                                  (asyncResult => context.EndSaveChanges(asyncResult)), null);
            }
            catch (StorageClientException e)
            {
                Debug.WriteLine("Error: {0}", e.Message);
                Debug.WriteLine("Extended error info: {0} : {1}",
                                e.ExtendedErrorInformation.ErrorCode,
                                e.ExtendedErrorInformation.ErrorMessage);
            }
        }
    }

    internal class StorageTestEntity : TableServiceEntity
    {
        public string Message { get; set; }
    }
}

WorkerRole.cs调用:

using System.Net;
using System.Threading;
using Microsoft.WindowsAzure.ServiceRuntime;
using log4net;

namespace WorkerRole1
{
    public class WorkerRole : RoleEntryPoint
    {
        public override void Run()
        {
            var storageWriter = new TableStorageWriter();
            while (true)
            {
                Thread.Sleep(10000);
                storageWriter.Write("Working...");
            }
        }

        public override bool OnStart()
        {
            ServicePointManager.DefaultConnectionLimit = 12;
            return base.OnStart();
        }
    }
}

使用 Windows Azure SDK for .NET 1.8 的示例。

最佳答案

您应该调用 EndSaveChangesWithRetries 而不是 EndSaveChanges,否则 EndSaveChanges 无法使用 BeginSaveChangesWithRetries 返回的 IAsyncResult 对象。那么,您可以尝试如下更改 End 方法调用吗?

context.BeginSaveChangesWithRetries(SaveChangesOptions.Batch,
    (asyncResult => context.EndSaveChangesWithRetries(asyncResult)),
    null);

对于您的其他问题,我建议为每个调用创建一个新的 TableServiceContext,因为 DataServiceContext 不是无状态的 ( MSDN ) 并且您使用异步调用实现 TableStorageWriter.Write 的方式可能允许并发操作。实际上,在 Storage Client Library 2.0 中,我们明确阻止使用单个 TableServiceContext 对象的并发操作。此外,创建 TableServiceContext 不会导致对 Azure 存储的请求。

关于c# - Azure 表中的异步插入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13769081/

相关文章:

azure - DocumentDB 模拟器作为 Windows 服务

C# Excel Interop - 调用 Worksheet.ExportAsFixedFormat 时抑制 'Publishing' 对话框

c# - .NET 获取自定义配置部分作为 NameValueCollection

C# HashSet<string> 到单个字符串

javascript - 如何从异步调用返回响应?

Microsoft 托管代理和并行作业上的 Azure 计费

c# - "is"的反义词是什么?

javascript - 为什么 Redux 的开发者使用中间件来处理异步而不是等待 promise 来解决?

javascript - 更改我的函数异步 : false to async: true with JQuery and Ajax

sql - 如何替换SQL表中的NULL值?