2012-12-29 50 views
3

我有一個烏鴉驅動的應用程序,我試圖實現級聯刪除捆綁。設置看起來很簡單,但映射設置部分從我們的關於級聯的1個文檔中有點不清楚。無論如何,這裏是我的設置,謝謝任何幫助。級聯使用級聯刪除捆綁ravendb

// 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. 

回答

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; 
} 
+0

我還爲後代添加了擴展方法到[Raven.Contrib項目](https://github.com/ravendb/ravendb.contrib)。 –

+0

謝謝,但不幸的是,這並不適合我。在這個項目中,我在創建相冊後添加照片。所以我加入和現有的專輯就像你的例子。當我保存照片時,現有相冊文檔中沒有元數據?我是否必須在相冊創建時創建一個空的元數據列表?這就是我的問題。我遵循了烏鴉文件,你的文件。不知道這裏發生了什麼 – user516883

+0

當我創建照片文檔時,元數據僅保存在SaveChanges()上。 – user516883