Ошибка при произнесении выражения «тип« T »должен быть ссылочным» > предикат внутри метода - PullRequest
1 голос
/ 28 марта 2020

Я пытаюсь изменить метод, чтобы он принимал параметр Expression<Func<T, Boolean>> predicate. Но когда я делаю это, это дает мне ошибку.

Вот старый метод:

    async static Task Delete() {
       var F = await cosmosManager.GetDocumentItemsAsync<LogF>(
            x => x.Activity == "F");
       await cosmosManager.DeleteDocumentItemAsync(F[0].Id);
    }

Вот новый метод:

await Delete<LogF>(x => x.Activity == "F");

async static Task Delete<T>(Expression<Func<T, Boolean>> predicate) {
   var F = await cosmosManager.GetDocumentItemsAsync<T>(predicate);
   await cosmosManager.DeleteDocumentItemAsync(F[0].Id);
}

Но это не работает, и я получаю эту ошибку здесь: cosmosManager.GetDocumentItemsAsync<T>

Ошибка CS0452: тип 'T' должен быть ссылочным типом, чтобы использовать его в качестве параметра 'T' в универсальном типе или методе c CosmosManager.GetDocumentItemsAsyn c (выражение> ) '

Вот код для GetDocumentItemsAsyn c:

    public async Task<List<T>> GetDocumentItemsAsync<T>(Expression<Func<T, Boolean>> predicate) where T : class
    {
        List<T> Items = new List<T>();
            collectionLink = UriFactory.CreateDocumentCollectionUri(databaseId, collectionId);
            var query = client.CreateDocumentQuery<T>(collectionLink)
                .Where(predicate)
                .AsDocumentQuery();
            while (query.HasMoreResults)
            {
                var retrivedData1 = await query.ExecuteNextAsync<T>();
                Items.AddRange(retrivedData1);
            }
        return Items;
    }

Может кто-нибудь подсказать мне, как я могу использовать параметр для выполнения части "где" метод и как я мог бы вызвать его с параметром:

x => x.Activity == "F"

Также это работает только для первой полученной записи [0]. Как я могу изменить его, чтобы он удалял все записи?

Ответы [ 2 ]

3 голосов
/ 28 марта 2020

Просто примените то же ограничение к вашему параметру типа , что и к параметру в GetDocumentItemsAsync<T>:

async static Task Delete<T>(Expression<Func<T, Boolean>> predicate) where T : class
{
    // Implementation as before
}

Это гарантирует, что T в вашем методе Delete подходит для T в GetDocumentItemsAsync.

Тогда у вас возникнет проблема, что свойство Id неизвестно в T. У вас есть базовый класс или интерфейс, который определяет это свойство? Если это так, добавьте это к ограничению.

Также это работает только для первой полученной записи [0]. Как я могу изменить его так, чтобы он удалял все записи?

Вы могли бы перебирать все результаты, удаляя по одному за раз, или использовать пакетное удаление, если Cosmos обеспечивает это функциональность. (Я ничего не вижу в этих строках.)

В зависимости от приложения вы можете распараллелить это, сначала вызывая DeleteDocumentItemAsync для каждого элемента, а затем используя Task.WhenAll, чтобы дождаться всех полученных результатов. задачи для завершения.

1 голос
/ 28 марта 2020

Также это работает только для первой найденной записи [0]. Как я могу изменить его так, чтобы он удалял все записи?

Этот код появляется для получения коллекции, но затем удаляет только первый элемент:

var F = await cosmosManager.GetDocumentItemsAsync<T>(predicate);
await cosmosManager.DeleteDocumentItemAsync(F[0].Id);

Возможно, это будет уместно для итерации коллекции:

var F = await cosmosManager.GetDocumentItemsAsync<T>(predicate);
foreach(var f in F)
  await cosmosManager.DeleteDocumentItemAsync(f.Id);

Если это Azure CosmosDB, может быть способ ускорить это, не перетаскивая все записи на клиент только для получения идентификатора и удаления по одному. Я не уверен, что посоветовать для вашего конкретного контекста, но недавно мне пришлось реализовать что-то, чтобы выборочно удалять миллионы Azure записей хранилища таблиц - Пакетное удаление в Windows Azure хранилище таблиц было полезный ресурс - по существу, использование средства, где предикат может быть отправлен на Azure для оценки. Я не знаю, применимо ли это / полезно для вашей ситуации

Если есть только несколько записей, которые нужно удалить, тогда этот упрощенный подход c может подойти; Джон упоминает WhenAll, и это, безусловно, было бы лучше для большего количества элементов - рассмотрите (если у вас огромное количество элементов и вам необходимо поддерживать отзывчивый интерфейс) либо механизм очереди, где вы помечаете элементы для удаления, и работает какой-то независимый фоновый процесс. через них или, может быть, какой-то огонь и забыть; Здесь много неизвестного.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...