0

少し好奇心。UserPhoto、UserMatchInterest、UserPreferenceオブジェクトのそれぞれのバッグを含むUserオブジェクトがあります。バッグ内の各アイテムに親ユーザーへの参照を指定し、nhibernateを使用して、ユーザーオブジェクトを初めて作成するときに、UserPhoto、UserMatchInterest、およびUserPreferenceオブジェクトを自動的に作成するようにソートされた双方向マッピングを取得しました。正常に機能するコレクションバッグ。UserIdを親Userオブジェクトに設定します。

例として、UserPhotoテーブルにはPhotoIdPK列とUserIdFK列があります。UserPhotoオブジェクトにはPhotoIdプロパティとUserプロパティ(UserIdではない)があるため、UserIdを保持するのではなく、親への参照を保持し、UsersPKに基づいてDB列にデータを入力します。

私が抱えている問題は、Userオブジェクトを一度に更新したい場合です。Userオブジェクトの残りの部分は正常に更新されますが、写真に関しては、データベースに新しい写真が作成されます。ASP.NET Webサイトとして受け入れられる以前のフォトセッションオブジェクトにまったくリンクされていないため、分離されたオブジェクトを処理する理由を理解できます。しかし、それは古いものを残します。したがって、写真ID 1と2があり、UserId=1の場合。更新後、UserId = 1の写真1、2、3、4が作成されます。写真1と2を削除してから、代わりに3と4を挿入します。

それらをコレクションとして個別に取得し、最初にトランザクションで削除しようとしましたが、メッセージが表示されます

Message = "deleted object would be re-saved by cascade (remove deleted object from associations)

削除するコードは次のとおりです

// First delete existing photos, interests and preferences


       var photos = from row in repository.GetItemsAsQuery<UserPhoto>()
                     where row.User.UserId == user.UserId
                     select row;
        repository.DeleteItems(photos.ToList());

        var interests = from row in repository.GetItemsAsQuery<UserMatchInterest>()
                        where row.User.UserId == user.UserId
                        select row;
        repository.DeleteItems(interests.ToList());

        var preferences = from row in repository.GetItemsAsQuery<UserPreference>()
                          where row.User.UserId == user.UserId
                          select row;
        repository.DeleteItems(preferences.ToList());

        // Now update the user object and re-add the above linked items
        repository.UpdateItem(user);

エラーはrepository.DeleteItems(interests.ToList());にスローされます。行では、最初の削除は問題なく通過します-それはすべてトランザクション内にありますが。

私の質問は、更新する必要のある他のオブジェクトのバッグがあるDB内のオブジェクトを更新する正しい方法にこれに近づいているかどうかです。IDを手動で設定せずに既存の写真オブジェクトを更新する方法がわかりません-ユーザーがすべての写真を置き換えたか、とにかく追加/削除した可能性があるため、既存の写真を削除して新しいものを再度追加する方がおそらくクリーンですが、既存の写真を削除するにはどうすればよいですか?このカスケードエラーが発生しないものはありますか?

4

1 に答える 1

0

あなたの説明から、私は次のクラスを想定しています

public class User
{
    public virtual int Id { get; set; }

    public virtual ICollection<Photo> Photos { get; private set; }
}

public class Photo
{
    public User Parent { get; set; }
    public virtual string Name { get; set; }
    public virtual byte[] Data { get; set; }
}

マッピングは次のようになります

public class UserMap : ClassMap<User>
{
    public UserMap()
    {
        Id(x => x.Id);

        HasMany(x => x.Photos)
            .AsSet()   // no duplicate entries, allows NH to optimise some things
            .Cascade.AllDeleteOrphan()
            .Component(c =>
            {
                c.ParentReference(x => x.Parent);
                c.Map(x => x.Name);
                c.Map(x => x.Data);
            });
    }
}

注: Cascade.AllDeleteOrphan は、コレクションの一部ではなくなったすべての子を自動的に削除します。

于 2012-11-29T13:23:17.100 に答える