1

この質問は以前にもあったと思いますので、あらかじめお詫び申し上げますが、検索に含める正しいキーワードがわかりません...

オブジェクトのプロパティの 1 つが切断された環境 (Web サイトなど) の他のプロパティのコレクションである場合、オブジェクトを更新 (または挿入) するための適切なパターンを理解するのに苦労しています。私の問題は、Web アプリケーションが完全なオブジェクトではなく、ID のコレクションのみを返すという考えに関係しています。これを説明する最善の方法は、コード スニペットを使用することだと思います。

次のオブジェクトが与えられた場合

Public Class User
  Public Property UserId As Integer
  Public Property Username As String
  Public Property Roles As ICollection(Of Role)
End Class

Public Class Role
  Public Property RoleId As Integer
  Public Property RoleName As String
  Public Property Users As ICollection(OF User)
End Class

Public Class EFDbContext
  Inherits Entity.DbContext

  Public Property Users As Entity.DbSet(Of User)
  Public Property Roles As Entity.DbSet(Of Role)
End Class

データベースは、Users、Roles、および RoleUsers の 3 つのテーブルで作成されます。

私は簡単に次のことができることを知っています

Dim db = New EFDbContext()

Dim r1 = New Role() With { .RoleName = "User" }
Dim r2 = New Role() With { .RoleName = "Admin" }

db.Roles.Add(r1)
db.Roles.Add(r2)

Dim u1 = New User() With { .UserName = "test1", .Roles = New List(Of Role) }
u1.Roles.Add(r1)

db.Users.Add(u1)

db.SaveChanges()

そして、両方の新しい役割をデータベースに保存し (RoleId の値をそれぞれ 1 と 2 に設定)、新しいユーザー (UserId の値に 1 を設定)、および RoleId 1 と UserId 1 の新しい Role-User エントリを保存します。

ただし、Web サイトのような接続されていないシナリオを扱う場合、ほとんどの人はビュー モデルを使用してユーザーからの入力を表し、エンティティにマップし直します。さらに、役割を表す値の場合、返されるデータには、役割を表す一意のキーのみが含まれる可能性が高くなります。例えば、

Public Class UpdatedUserViewModel
  Public Property UserId As Integer
  Public Property Username As String
  Public Property RoleIds As ICollection(Of Integer)
End Class

...
...

Dim userEntity = db.Users.Find(user.Values.UserId)
AutoMapper.Mapper.Map(userValues, userEntity)

したがって、userEntity.Roles コレクションには 1 つのアイテムが含まれている可能性がありますが、マッパーはおそらく次のようなエントリを追加しただけです。

ForMember(Function(u) u.Roles, Sub(m) m.MapFrom(Function(su) su.RoleIds.Select(Function(r) New Role() With {.RoleId = r})))

ここで問題が発生します。SaveChanges()メソッドが呼び出されると、.RoleName プロパティが Nothing であるため、EF は検証エラーをスローします。

この状況はどのように処理されますか? ロールを手動でループして、データベースからそれぞれをフェッチする必要がありますか? マッピング ツールを使用できないのですか? 「欠落している」プロパティに偽の値を指定してから、ループしてそれらを Unchanged としてマークしますか?

これが長いことはわかっていますが、ウォークスルーが役立つと思いました...

ありがとう。

4

1 に答える 1

1

このアルゴリズムを使用できます

  • ルート エンティティから始めます。
    • タイプ A などのルート エンティティごとに、ナビゲーション プロパティを除く a のプロパティを設定します (少なくともすべての必須プロパティ (null 非許容))。
    • As をコンテキストに追加します。
  • 次に、タイプ B の b などの子エンティティ (正確に 1 つの A を持たなければならないエンティティ) を準備します。
    • b のプロパティを設定します (ナビゲーション、少なくともすべての非 nullables を除く)。
    • 各 b について、その a に b を追加します (egaChildren.Add(b))。
  • 上記の子エンティティで続行

    ...

  • 変更を保存して適用する

DB に既に存在し、コンテキストを介してまだアクセスされていない、null 非許容のナビゲーションを持つエンティティがある場合は、設定する代わりに ID で関係を設定できます (モデル内のプロパティに FK をマップしたと仮定します)。エンティティ自体。

ID がストアで生成されていない場合は、ID も設定してください。存在する場合は、EDMX で生成されたストアとして定義されていることを確認してください。

DB に FK がある場合は、挿入が正しい順序で行われるように EDMX がそれらを認識していることを確認してください (または、Oracle を使用している場合は、必要に応じて代わりに遅延制約を使用してみてください)。

于 2012-06-08T23:10:17.530 に答える