3

Raven 駆動のアプリケーションがあり、Cascading Deletion Bundle を実装しようとしています。セットアップは非常に単純に見えますが、カスケードに関する 1 つのドキュメントから、マッピングのセットアップ部分が少しわかりません。とにかく、これが私のセットアップです。助けてくれてありがとう。

// An album class with no reference to photos
class Album
{
    public string Id { get; set; } //ID for album from raven
}

// A photo class with a reference to its parent album
class Photo
{
    public string Id { get; set; } //ID for photo from raven
    public string PhotoName { get; set; }
    public Album PhotoAlbum  { get; set; }
}

// On album store 
session.Store(album);
session.Advanced.GetMetadataFor(album)["Raven-Cascade-Delete-Documents"] =
    RavenJToken.FromObject(new[] { album.Id });

// THIS DOES NOT WORK, But I was assuming that it would search for each document
// with a reference to an album and delete it. 
4

1 に答える 1

3

まず、ドキュメント間の参照をモデル化する場合、ドキュメント全体ではなく、外部ドキュメント キーを参照する必要があります。これで、ドキュメントにアルバムが埋め込まれます。代わりにこれを行います:

public class Photo
{
    public string Id { get; set; }
    public string PhotoName { get; set; }
    public string AlbumId { get; set; }
}

カスケード削除に関しては、バンドルはドキュメントを削除するときにメタデータを参照するだけで、参照されているドキュメントをすべて削除します。最初からドキュメントのリストを作成するのには役立ちません。あなたはそれを自分でしなければなりません。写真を追加するたびに、アルバムを読み込み、写真の ID をアルバムのカスケード削除リストに追加します。

そのため、アルバムと最初の数枚の写真を保存する場合:

using (var session = documentStore.OpenSession())
{
    var album = new Album();
    session.Store(album);

    var photoA = new Photo { PhotoName = "A", AlbumId = album.Id };
    var photoB = new Photo { PhotoName = "B", AlbumId = album.Id };
    var photoC = new Photo { PhotoName = "C", AlbumId = album.Id };
    session.Store(photoA);
    session.Store(photoB);
    session.Store(photoC);

    session.Advanced.AddCascadeDeleteReference(album,
                                               photoA.Id,
                                               photoB.Id,
                                               photoC.Id);

    session.SaveChanges();
}

その後、既存のアルバムに写真を追加

using (var session = documentStore.OpenSession())
{
    // you would know this already at this stage
    const string albumId = "albums/1";

    var photoD = new Photo { PhotoName = "D", AlbumId = albumId };
    session.Store(photoD);

    var album = session.Load<Album>(albumId);
    session.Advanced.AddCascadeDeleteReference(album, photoD.Id);

    session.SaveChanges();
}

上記で使用したAddCascadeDeleteReference拡張メソッドは次のとおりです。自分で行うこともできますが、これにより作業が少し簡単になります。静的クラスに入れます。

public static void AddCascadeDeleteReference(
  this IAdvancedDocumentSessionOperations session,
  object entity, params string[] documentKeys)
{
    var metadata = session.GetMetadataFor(entity);
    if (metadata == null)
      throw new InvalidOperationException(
        "The entity must be tracked in the session before calling this method.");

    if (documentKeys.Length == 0)
      throw new ArgumentException(
        "At least one document key must be specified.");

    const string metadataKey = "Raven-Cascade-Delete-Documents";

    RavenJToken token;
    if (!metadata.TryGetValue(metadataKey, out token))
        token = new RavenJArray();

    var list = (RavenJArray) token;
    foreach (var documentKey in documentKeys.Where(key => !list.Contains(key)))
        list.Add(documentKey);

    metadata[metadataKey] = list;
}
于 2012-12-30T00:06:12.593 に答える