2

AzureテーブルストレージエミュレーションでEFとAutoMapperを使用しています。

Fragment(シリアライズ可能なDTO)とFragmentEntity(EF永続化DO)の2つのタイプがあります。AutoMapperを使用してDTOからDOにマップし、PUT呼び出しで永続化し、GET呼び出しでその逆を行います。

問題は、EFとAutoMapperの両方に関する私の経験不足です。FragmentEntityクラスを(見つけたドキュメントに従って)データベースでフラグメントのIDを生成するように構成しました(以下を参照)。

エンティティIDの定義:

 [Key]
 [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
 public int? Id { get; set; }

実行時に、httpクライアントは新しいコンテンツ(フラグメント)を使用してRESTPUT呼び出しを行います。これはWCFを介して受信され、次のようにフラグメントにシリアル化されます。

 [OperationContract]
 [WebInvoke(UriTemplate = "/Fragments", Method = "PUT")]
 void PutFagment(Fragment fragment);

デバッグ中にコードをステップオーバーすると、受信したID値はnullになります(IDプロパティをオプションとして定義したため)。

 public void PutFagment(Fragment fragment)
 {
      var fragmentEntity = Mapper.Map<Fragment, FragmentEntity>(fragment);
      _fragmentContext.Add(fragmentEntity);
 }

 [DataMember]
 public virtual int? Id { get; set; }

それをオプションとして定義することが賢明な動きであったかどうかはわかりません。これを行ったのは、オプションでない場合、値のデフォルトがゼロになり、オートマッパーがターゲットのFragmentEntityにマップし、その後、データベース内のすべてのキーがゼロ(明らかに間違っている)になるためです。

アプリケーションコードに値を設定しないようにFragmentEntityIdもオプションにしたので、nullの場合はデータベースの生成が発生する可能性がありますが、発生していないように見えます。

<Fragment><Id i:nil="true"/><Name>Drei</Name><Type>3</Type></Fragment>

私の問題:

  1. 両方のクラスでIdをオプションにするという決定は正しくないと思います。このケースを適切に処理するAutoMapper構成がいくつかあり、両方を非オプションのままにしておくことができると思います。
  2. DatabaseGenerated属性が有効にならない理由がわかりません。
4

1 に答える 1

0

したがって、開発者は、独自の行キーを生成するための紺碧のテーブルストレージを担当していることがわかります。これは、TableServiceEntityを拡張するFragmentEntityに対して行われます。別名、プロバイダーはデータベースキーの生成をサポートしません。開発者はこれを所有する必要があります。

これの意味は:

  1. ID生成コードを所有している必要があります。
  2. でId属性を定義する必要はありませんTableServiceEntity。代わりに、AutoMapper構成で両方向に適切なマッピングを提供するだけです。

IDはクライアントが指定しないでください(サーバーの責任です)。したがって、DTOから永続化されたDOへのマッピングは、デフォルトで設定されている値を、新しく生成されたGuidで上書きします(以下のコードを参照)。

Mapper.Configuration.CreateMap<Fragment, FragmentEntity>()
      .ForMember(dest => dest.RowKey,
                 expression => expression.ResolveUsing(source => Guid.NewGuid().ToString()))
// NB: you are also required to provide a partition key for TableServiceEntities
      .ForMember(dest => dest.PartitionKey,
                 opt => opt.ResolveUsing(source => PartitionKeyConstants.LocalPartitionKey));

次に、FragmentEntityからFragmentへの反対方向のマッピングを構成して、DTOのId属性をFragmentEntityのRowKey値に設定する必要があります。

Mapper.Configuration.CreateMap<FragmentEntity, Fragment>()
      .ForMember(dest => dest.Id, 
                 expression => expression.ResolveUsing(source => source.RowKey));

マッピング登録を処理するために、マッピングコードがGlobal.asax.csに登録されています。いつかこれをIoCコンテナに移動します。

この変更の結果、FragmentEntityでIDを定義しなくなり、Fragmentクラスで定義されたId属性はオプションではなくなりました。

[DataMember]
public virtual Guid Id { get; set; }

注意:intキーを追跡してインクリメントするよりも、一意のGuid値を生成する方が簡単なため、Guidを使用しました。また、これは、次のintキー値を確認するときにdb-lockボトルネックを導入していないことを意味します。

于 2012-11-30T09:31:11.383 に答える