Azure存储客户端v4.1—期望非原语类型的值

本文关键字:原语 类型 期望 存储 客户端 v4 Azure | 更新日期: 2023-09-27 18:10:22

我最近升级了我的ASP。. NET项目(MVC5)的目标Azure SDK 2.3与存储库4.1和遇到一个奇怪的错误,当我试图保存任何东西到表存储。

错误:

类型为"Microsoft.WindowsAzure.Storage"的未处理异常。在Microsoft.WindowsAzure.Storage.dll

附加信息:指定了原始值;但是,非基本类型的值是必需的。

我的模型通过存储库进入表存储,存储库使用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库之外。

是否内部发生了一些变化,使我的模式不再有效?

Azure存储客户端v4.1—期望非原语类型的值

既然没有什么(尚未)对这个错误在网上,这是几乎唯一的地方讨论,我将添加一个解决方案,即使我的上下文是不同于你的。错误是完全相同的,所以我猜它来自同一个地方。

对我来说,是继承的主键导致了这个问题。序列化实体的主键必须是自然的,不能被覆盖。如果Class有一个ID属性,那么DerivedClass也必须将ID属性声明为"new",或者将ID属性从Class移到DerivedClass。

这里有更多的细节:http://jerther.blogspot.ca/2014/12/aspnet-odata-v4-primitive-value-was.html

我相信这是一个bug,而不是一个限制,因为继承的键在实体框架和Fluent API中工作得很好。

最后,我决定升级所有的存储库代码,以摆脱基于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);
        }
}