使用Cascading Deletion Bundle与ravendb级联

时间:2012-12-29 21:14:25

标签: c# ravendb

我有一个乌鸦驱动的应用程序,我正在尝试实现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. 

1 个答案:

答案 0 :(得分: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;
}