Доступ к хранилищу Azure в приложении ASP.NET Core с помощью подключенных служб

Я пытаюсь следовать статье Доступ к Azure Хранилище в приложении ASP.NET Core с использованием подключенных служб в ASP.NET Core 1.1, чтобы подключить мое веб-приложение к таблицам Azure.

я создал

public interface ITableRepositories
{
    void CreateRecord(Record record);
    List<Record> GetRecords();
    Record GetRecord(string key, string partitionKey = "record");
}

Но проблема в том, что под ASP.NET Core и Microsoft.WindowsAzure.Storage nuget у меня нет доступа к методам Syncronous.

Итак, например, этот код класса OperationService:

public class TableClientOperationsService : ITableRepositories
{
    CloudStorageAccount storageAccount;
    CloudTableClient tableClient;
    IConfigurationRoot configs;

    public TableClientOperationsService(IConfigurationRoot c) {
        this.configs = c;
        var connStr =  this.configs.GetSection("MicrosoftAzureStorage:[...]");
        storageAccount = CloudStorageAccount.Parse(connStr.Value);
        tableClient = storageAccount.CreateCloudTableClient();
        CloudTable table = tableClient.GetTableReference("Book");
        table.CreateIfNotExists();
    }

Я вынужден сделать асинхронный вариант коннектора:

public class TableClientOperationsService: ITableRepositories
{
    CloudStorageAccount storageAccount;        
    CloudTableClient tableClient;        

    public TableClientOperationsService(IOptions<AppSecrets> optionsAccessor) {
        string connectionString = optionsAccessor.Value.MyProjectTablesConnectionString;
        storageAccount = CloudStorageAccount.Parse(connectionString);
        tableClient = storageAccount.CreateCloudTableClient();
        CloudTable table = tableClient.GetTableReference("Record");


        // ??? How to use the async method in constructor?
        var created = await table.CreateIfNotExistsAsync();
    }
}

Итак, каким должен быть асинхронный подход для этого? Должен ли я вместо этого создать статический конструктор?

ПС.

Также "асинхронная" операция CreateRecord

от

public void CreateBook(Book bk)
{
    Random rnd = new Random();
    bk.BookId = rnd.Next(100);
    bk.RowKey = bk.BookId.ToString();
    bk.PartitionKey = bk.Publisher;
    CloudTable table = tableClient.GetTableReference("Book");
    TableOperation insertOperation = TableOperation.Insert(bk);
    table.Execute(insertOperation);
}

следует преобразовать в (?)

public void CreateRecord(Record record)
{
    // var rowKey = (DateTime.MaxValue.Ticks - DateTime.UtcNow.Ticks).ToString("d19");
    TableOperation insertOperation = TableOperation.Insert(record);
    this.RecordTable.ExecuteAsync(insertOperation).Wait();
}

Или скорее в

public Task<TableResult> CreateRecord(Record record)
{
    TableOperation insertOperation = TableOperation.Insert(record);
    return this.RecordTable.ExecuteAsync(insertOperation);
}

Наконец я сделал это как

public async Task<bool> CreateRecord(Record record)
{
    TableOperation insertOperation = TableOperation.Insert(record);
    await this.RecordTable.ExecuteAsync(insertOperation);
    return true;
}

так же

public Record GetRecord(string key, string partitionKey = "record")
{
    Record myRecord = null;
    TableOperation operation = TableOperation.Retrieve<Record>(partitionKey, key);
    // ?
    myRecord = recordTable.ExecuteAsync(operation).Result as Record;

}

person serge    schedule 19.07.2017    source источник
comment
Для Create я бы не возвращал TableResult, так как это зависит от типа хранилища. Поскольку вы реализуете репозиторий, я бы либо вернул логическое значение, указывающее на успех, либо свойство Result класса TableResult, типизированное для объекта, который вы вставляете. В основном я бы реализовал репозиторий, чтобы иметь асинхронные методы и вызывать их соответствующим образом.   -  person rickvdbosch    schedule 19.07.2017
comment
Вы имеете в виду, что я должен вернуть Task‹bool› для CreateAsync? Это немного сложно для новичка, я не нашел много статей о   -  person serge    schedule 19.07.2017
comment
как и в обновленном ОП, я создал public async Task<bool> CreateRecord(Record record) не уверен, что все в порядке, но, по крайней мере, он компилируется   -  person serge    schedule 19.07.2017


Ответы (1)


Простым решением было бы просто подождать() асинхронных методов:

public class TableClientOperationsService: ITableRepositories
{
    CloudStorageAccount storageAccount;        
    CloudTableClient tableClient;        

    public TableClientOperationsService(IOptions<AppSecrets> optionsAccessor) 
    {
        string connectionString = optionsAccessor.Value.MyProjectTablesConnectionString;
        storageAccount = CloudStorageAccount.Parse(connectionString);
        tableClient = storageAccount.CreateCloudTableClient();
        CloudTable table = tableClient.GetTableReference("Record");


        table.CreateIfNotExistsAsync().Wait();
    }
}

Если вам нужен результат асинхронного метода, попробуйте Result:

var created = table.CreateIfNotExistsAsync().Result;

Лично я не большой поклонник конструкторов с (слишком) большой функциональностью. Особенно, если это (относительно) может занять некоторое время, например, подключение к StorageAccount. Вы можете реализовать метод Initalize(), который может быть асинхронным. Или вы можете реализовать ленивое свойство, которое создает CloudTable (и все необходимое для этого) только при первом использовании свойства. Это также позволяет вам повторно использовать CloudTable в течение жизни вашего класса.

Это будет выглядеть примерно так:

private CloudTable _table;

private CloudTable Table
{
    get
    {
        if (_table == null)
        {
            var storageAccount = CloudStorageAccount.Parse(connectionString);
            var tableClient = storageAccount.CreateCloudTableClient();
            _table = tableClient.GetTableReference("Record");

            _table.CreateIfNotExistsAsync().Wait();
        }

        return _table;
    }
}
person rickvdbosch    schedule 19.07.2017
comment
спасибо ... хорошая идея ... просто Wait () возвращает void ... Так что, вероятно, здесь нет авторства. - person serge; 19.07.2017
comment
Спасибо за идею! Просто не могли бы вы взглянуть на редактирование PS (CreateRecord), потому что это в основном тот же вопрос... - person serge; 19.07.2017