NServicebus 6、Azure Storage Persistence、Sagas 和复杂类型(集合)

NServicebus 6, Azure Storage Persistence, Sagas and complex types (collections)

我看到过与此答案类似的问题,它们使用 SQL 服务器和 Nhibernate 持久性。但是 Azure 存储怎么样?

我有一个 class 保存 Saga 数据。其中包含一个 属性 是一个集合:

public class ResetPolicyData : ContainSagaData
{
    public int NumberOfEmailsInGroup { get; set; }
    public Guid EmailGroupId { get; set; }

    public List<PasswordResetInformation> PasswordResetInformation { get; set; }
}

PasswordResetInformation 包含几个简单的字符串属性,仅此而已。

当 saga 尝试将数据保存到 Azure 存储时,出现以下错误:

The property type 'List 1' is not supported in windows azure table storage at NServiceBus.Persistence.AzureStorage.AzureSagaPersister.ToDictionaryTableEntity(Object entity, DictionaryTableEntity toPersist, IEnumerable`1 properties) in C:\Build\src\NServiceBus.Persistence.AzureStorage\SagaPersisters\AzureSagaPersister.cs:line

在我的 EndpointConfig 中,我有以下内容,所以我想我有点期待 NServiceBus 神奇地将 PasswordResetInformation 序列化为 JSON 并存储它:

endpointConfiguration.UseSerialization<JsonSerializer>();

所以我的问题是:有没有办法将 Saga Data 中的列表或其他集合持久保存到 AzureStorage?

仅 Azure 存储supports primitive types. Therefore, anything else should be serialized (JSON, like you've suggested would work) and stored as a simple type as well. This should be documented and here's a link 用于跟踪文档进度。

这是我的工作around/hack来完成这项工作:

public class ResetPolicyData : ContainSagaData
{
    public int NumberOfEmailsInGroup { get; set; }
    public string Email { get; set; }

    /// <summary>
    /// Dont reference directly. Only here for persisting data to Azurestorage. Use
    /// AddPasswordResetInformation/GetPasswordResetInformation instead.
    /// </summary>
    public string PasswordResetInformationJson { get; set; }

    #region Handle Searilize and Desearilize PasswordResetInformation 

    public void AddPasswordResetInformation(PasswordResetInformation value)
    {
        if (value == null) return;

        //Hydrate collection
        var collection = string.IsNullOrEmpty(PasswordResetInformationJson) ? 
            new List<PasswordResetInformation>() : JsonConvert.DeserializeObject<List<PasswordResetInformation>>(PasswordResetInformationJson);

        //Check is unique before adding
        if(!collection.Contains(value)) collection.Add(value);

        PasswordResetInformationJson = JsonConvert.SerializeObject(collection);
    }

    public List<PasswordResetInformation> GetPasswordResetInformation()
    {
        return string.IsNullOrEmpty(PasswordResetInformationJson) ? 
            new List<PasswordResetInformation>() : JsonConvert.DeserializeObject<List<PasswordResetInformation>>(PasswordResetInformationJson);
    }

    #endregion
}