Клиент хранилища Azure версии 4.1.1 — ожидалось значение непримитивного типа

#c# #asp.net #azure #azure-table-storage

#c# #asp.net #azure #azure-table-storage

Вопрос:

Я недавно обновил свой ASP.NET проект (MVC5) нацелен на Azure SDK 2.3 с библиотекой хранения 4.1, и я сталкиваюсь со странной ошибкой, когда пытаюсь сохранить что-либо в хранилище таблиц.

Ошибка:

Необработанное исключение типа ‘Microsoft.WindowsAzure.Хранение.В Microsoft произошло исключение StorageException.WindowsAzure.Storage.dll

Дополнительная информация: было указано примитивное значение; однако ожидалось значение непримитивного типа «.

Мои модели попадают в хранилище таблиц через репозитории, которые используют a TableServiceContext для добавления, обновления, удаления, сохранения.

Я следую этому шаблону для своих моделей:

 [System.Data.Services.Common.DataServiceKey(new string[] { "PartitionKey", "RowKey" })]
public class PersistedAlert : Alert, ITableEntity
{
    public string PartitionKey
    {
        get { return this.StudentId; }
        set { this.StudentId = value; }
    }

    public string RowKey
    {
        get { return this.Id; }
        set { this.Id = value; }
    }

    public DateTime Timestamp { get; set; }

    public new int Type { get; set; } //hides Enum type in Alert base class
}
 

Во время обновления мне нужно было поменять местами все мои ссылки на

System.Data.Services.*

для

Microsoft.Data.Services.*

…в дополнение к библиотекам OData.

Что-то изменилось внутри, что делает мой шаблон недействительным?

Комментарии:

1. У меня та же ошибка, с пустым ожидаемым типом, с использованием Web API 2 и OData V4 … нет абсолютно никакой помощи в этой ошибке, что когда-либо. Это сводит меня с ума!

Ответ №1:

Поскольку в сети нет ничего (пока) об этой ошибке, и это практически единственное место, где она обсуждается, я добавлю решение, даже если мой контекст отличается от вашего. Ошибка точно такая же, поэтому я предполагаю, что она происходит из того же места.

Для меня причиной проблемы был унаследованный первичный ключ. Первичный ключ сериализованного объекта должен быть естественным и не переопределяться. Если у класса есть свойство ID, DerivedClass также должен будет объявить свойство ID как «новое», или свойство ID должно быть перемещено из Class в DerivedClass.

Вот более подробная информация: http://jerther.blogspot.ca/2014/12/aspnet-odata-v4-primitive-value-was.html

Я действительно считаю, что это ошибка, а не ограничение, поскольку унаследованный ключ очень хорошо работает с Entity Framework и Fluent API.

Я надеюсь, что это поможет и сэкономит время.

Комментарии:

1. Это случилось со мной, когда я использовал fluent API для сопоставления поля с тем же именем, что и у другого поля. В обеих наших ситуациях я считаю, что эта ошибка вызвана двумя полями, сопоставленными с одним и тем же именем.

Ответ №2:

В конце я решил обновить весь код репозитория, чтобы отказаться от устаревшего WCF TableServiceContext -кода и вместо этого совершать вызовы через CloudTable . Я могу только предположить, что что-то внутренне изменилось в одной из вышеупомянутых библиотек, что привело к проблеме, которую я наблюдал.

В дополнение к изменению кода репозитория, мне также нужно было обновить свои сущности для наследования от Azure ITableEntity (раньше у меня был свой вкус), например:

 public class PersistedAlert : Alert, Microsoft.WindowsAzure.Storage.Table.ITableEntity
{
        public string PartitionKey
        {
            get { return this.StudentId; }
            set { this.StudentId = value; }
        }

        public string RowKey
        {
            get { return this.Id; }
            set { this.Id = value; }
        }

        public DateTimeOffset Timestamp { get; set; }

        public string ETag { get; set; }

        public void ReadEntity(IDictionary<string, Microsoft.WindowsAzure.Storage.Table.EntityProperty> properties, Microsoft.WindowsAzure.Storage.OperationContext operationContext)
        {
            Microsoft.WindowsAzure.Storage.Table.TableEntity.ReadUserObject(this, properties, operationContext);
        }

        public IDictionary<string, Microsoft.WindowsAzure.Storage.Table.EntityProperty> WriteEntity(Microsoft.WindowsAzure.Storage.OperationContext operationContext)
        {
            return Microsoft.WindowsAzure.Storage.Table.TableEntity.WriteUserObject(this, operationContext);
        }
}