基本的に、エンティティ フレームワークでこの一連のイベントを実行しようとしています。
- 新しいアカウントを作成する
- 既存のアカウントを取得する
- すべてのデータを古いアカウントから新しいアカウントに移動します (トランザクション、ユーザーなど)
- 古いアカウントを削除する
単一の ObjectContext 内で、これをすべて「一度に」実行しています。
コンテキストで SaveChanges を呼び出すと失敗します。外部キー制約エラーが発生します。
これを SQL プロファイラーで確認したところ、エンティティ フレームワークが更新を送信しておらず、選択したものだけを送信してから削除したことがわかりました。
なぜそのように機能するのかはちょっと理解できますが、SaveChanges() を 2 回呼び出す必要なく、適切に機能させる方法が必要です。
うまくいけば。
私のマージ機能は基本的に次のようになります
public void Merge(Account newAccount, Account oldAccount)
{
// ...
foreach (var user in oldAccount.Users.ToList())
{
oldAccount.Users.Remove(user);
newAccount.Users.Add(user);
}
// ...
_unitOfWork.Accounts.Delete(oldAccount);
}
オブジェクトは、EF4 POCO エンティティ ジェネレーターによって作成された POCO オブジェクトです。クラス全体を貼り付けるのを避けるために、'fixup' 機能を持つ関連付けプロパティの 1 つだけをここに示します。
public virtual ICollection<User> Users
{
get
{
if (_users == null)
{
var newCollection = new FixupCollection<User>();
newCollection.CollectionChanged += FixupUsers;
_users = newCollection;
}
return _users;
}
set
{
if (!ReferenceEquals(_users, value))
{
var previousValue = _users as FixupCollection<User>;
if (previousValue != null)
{
previousValue.CollectionChanged -= FixupUsers;
}
_users = value;
var newValue = value as FixupCollection<User>;
if (newValue != null)
{
newValue.CollectionChanged += FixupUsers;
}
}
}
}
private void FixupUsers(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null)
{
foreach (User item in e.NewItems)
{
item.Account = this;
}
}
if (e.OldItems != null)
{
foreach (User item in e.OldItems)
{
if (ReferenceEquals(item.Account, this))
{
item.Account = null;
}
}
}
}