2

ステートフルサービスファブリックアプリケーションで信頼できるキューを使用しています。 私はエンキュー方法がIReliableQueueシリアル化エラーをエンキュー

に使用されるコードを例外をスローして、アイテムをエンキューしようとしていては例外

種類を投げている、myQueue.EnqueueAsyncに

protected override async Task RunAsync(CancellationToken cancellationToken) 
     { 
      ICommand myItem = new CreateCommand() 
      { 
       Data = "Sample Data", 
       Id = Guid.NewGuid(), 
       TenentName = "SampleTenant" 
      }; 
      var myQueue = await this.StateManager.GetOrAddAsync<IReliableQueue<ICommand>>("CommandQueue"); 
      using (var tx = StateManager.CreateTransaction()) 
      { 
       await myQueue.EnqueueAsync(tx, myItem, TimeSpan.FromSeconds(4), cancellationToken); 
       await tx.CommitAsync(); 
      } 
      using (var tx = StateManager.CreateTransaction()) 
      { 
       var dq = await myQueue.TryDequeueAsync(tx); 
       await tx.CommitAsync(); 
      } 
     } 
    } 

    public interface ICommand 
    { 
     Guid Id { get; set; } 
     string TenentName { get; set; } 
    } 


    public class CreateCommand : ICommand 
    { 
     public Guid Id { get; set; } 
     public string TenentName { get; set; } 
     public string Data { get; set; } 
    } 

です'TestService.CreateCommand'、データコントラクト名が の場合 'CreateCommand:http://schemas.datacontract.org/2004/07/TestService'は ではありません。 DataContractSerializerを使用している場合、または既知のタイプのリスト(例えば、KnownTypeAttribute 属性を使用するか、 シリアライザに渡される既知のタイプのリストに追加するなど)を静的に知らないタイプを静的に追加する場合は、DataContractResolverの使用を検討してください。

System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeAndVerifyTypeで

スタックトレース(のDataContract のDataContract、XmlWriterDelegatorのXmlWriter、オブジェクトobj、ブール verifyKnownType、RuntimeTypeHandle declaredTypeHandle、タイプ たdeclaredType) システムで.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithXsiTypeAtTopLevel(DataContract dataContract、XmlWriterDelegator xmlWriter、Object obj、 R System.Runtime.Serialization.DataContractSerializer.InternalWriteObject(XmlWriterDelegator ライター、オブジェクトグラフ、DataContractResolver dataContractResolver)で System.Runtime.Serialization.DataContractSerializer.InternalWriteObjectContent(XmlWriterDelegator ライター、オブジェクトグラフ、DataContractResolver dataContractResolver)でuntimeTypeHandle originalDeclaredTypeHandle、タイプGraphTypeと) Microsoft.ServiceFabric.Replicator.DataContractStateSでSystem.Runtime.Serialization.XmlObjectSerializer.WriteObject(XmlDictionaryWriter ライター、オブジェクトグラフ)で System.Runtime.Serialization.XmlObjectSerializer.WriteObjectHandleExceptions(XmlWriterDelegator ライター、オブジェクトグラフ、DataContractResolver dataContractResolver)で System.RuntimeでSystem.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccessでSystem.Fabric.Store.TStore 5.<AddAsync>d__4.MoveNext() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.ServiceFabric.Data.Collections.DistributedQueue 1.d__9.MoveNext(AT erializer 1.Write(T value, BinaryWriter binaryWriter) at System.Fabric.Store.TStore 5.GetValueBytes(TValue currentValueは、TValue newValueに)) (タスク タスク) System.Runtime.CompilerServices.TaskAwaiter.GetResultで.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(タスク タスク)() DでTestService.TestService.d__2.MoveNext()で
:プロジェクト\ \ローカル\ ReliableSerialization \アプリケーション1 \ TestService \ TestService.cs: 51行目 でSystem.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(タスク タスク) システム Microsoft.ServiceFabric.Services.Runtime.StatefulServiceReplicaAdapter.d__f.MoveNext(で.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(タスク タスク))

私はそれがうまく働いたコンクリート型を使用するコードを変更したとき。

は、私の場合IReliableQueue<CreateCommand>

にそれがうまく働きました。

私のコードの参照:https://github.com/Azure-Samples/service-fabric-dotnet-iot/blob/master/src/gateway/IoTProcessorManagement.Common/WorkManagement/WorkManager.cs

+0

'DataContractSerializer'は、インターフェイスではなく具体的​​な型をシリアル化します。 「DataContractSerializerを使用してインターフェイスの一覧をシリアル化する」(https://stackoverflow.com/questions/14937097/serializing-a-list-of-interfaces-using-the-datacontractserializer)を見てください。 – dbc

答えて

3

あなたがのDataContractとデータメンバーがあなたのタイプの属性、およびので、データコントラクトのシリアル化を使用すると、インターフェイス上のDataContract属性を置くことができない仕組みを実装の欠落しています。サービスファブリックはオブジェクトへの参照を内部的に保存し、デキューするときにその参照を戻すため、オブジェクトのコミット時にセカンダリに送信するときにシリアル化します。上記の属性を忘れると、時には動作するように見えるが、トランザクションをコミットするか、サービスが再開するまで一見細かく実装されたオブジェクトがあるだろうということである(アップグレードの場合、そのノードが何らかの理由で)空になります(属性がないフィールドはnull/defaultになります)。

データコントラクトの多態性を利用するには、基本クラスとKnownType属性を使用できます。これは、削除コマンドを追加した例です。

[DataContract] 
[KnownType(typeof(CreateCommand))] 
[KnownType(typeof(DeleteCommand))] 
public class BaseCommand 
{ 
    [DataMember] 
    public Guid Id { get; set; } 

    [DataMember] 
    public string TenentName { get; set; } 
} 

[DataContract] 
public class CreateCommand : BaseCommand 
{ 
    [DataMember] 
    public string Data { get; set; } 
} 

[DataContract] 
public class DeleteCommand : BaseCommand 
{ 
    [DataMember] 
    public string SomeOtherData { get; set; } 
} 

も知られているタイプの属性は、サブタイプを、プログラムを発見する機能を渡しサポートしていますが、それは奇妙と診断するのが困難な方法でアップグレードを破るだろうとそれを使用しないでください。

関連する問題