2012-12-11 63 views
3

仍然只是ravendb中的首發。我懷疑raven db是否支持某種參照完整性。在ravendb中刪除級聯可能

這裏是我的懷疑和工作..

我的文檔類型的屏幕,如下

public class Screens 
    { 
     public String Id { get; set; } 
     public String ScreenName { get; set; } 
} 

,另一個名爲RightsDeclaration如下

public class RightsDeclaration 
    { 
     public RightsDeclaration() 
     { 
      _screenrights = new List<ScreenRight>(); 
     } 

     public String Id { get; set; }// Role Name 
     List<ScreenRight> _screenrights; 
     public List<ScreenRight> ScreenRights { get { return _screenrights; } set { _screenrights = value; } } 
} 

現在屏幕權益類看起來文件如下所示,屏幕名稱字段如下

public class ScreenRight : 
    { 

     public String ScreenName { get; set; } 
     public Boolean Create { get; set; } 
     public Boolean Read { get; set; } 
     public Boolean Update { get; set; } 
     public Boolean Delete { get; set; } 
     public Boolean Approve { get; set; } 
     public Boolean Access { get; set; } 
     public Boolean Print { get; set; } 
     public Boolean Email { get; set; } 
} 

現在首先我將創建一些屏幕列表,然後爲每個角色 分配權限,並提及屏幕名稱和權限列表。到目前爲止,一切都很順利。現在,如果我要刪除屏幕類中的屏幕名稱,但屏幕權限仍然存在於權限聲明中。是否有可能從userrights文件中刪除相應的屏幕權限? 如果是這樣,請提及查詢或想法做以上事情.. 在此先感謝..

回答

3

Raven不支持真正的參照完整性,這不是文檔數據庫通常感興趣的東西。但是,您可以實現同樣的效果。

首先,我不會通過名稱來引用,屏幕ID是一個更好的密鑰,因爲您可以通過它加載。如果您還想在您的課堂上捕獲屏幕名稱,那很好,但這是次要的問題。

此外,還有一個小問題,但儘量保持您的實體/文檔名稱單數。 Screen而不是Screens。它會爲你節省一些麻煩。

處理刪除的一種方法是在刪除主文件時專門更新引用文檔。如果您在同一會話中進行此操作,則您有交易保證。您必須考慮分頁查詢結果。

using (var session = documentStore.OpenSession()) 
{ 
    var screen = session.Load<Screen>(screenId); 
    if (screen != null) 
    { 
     // Set up some variables to help with pagination. 
     var now = DateTime.UtcNow; 
     const int pageSize = 1024; 
     var page = 0; 

     while (true) 
     { 
      // Get all rights that use this screen. 
      // Waiting for nonstale results is appropriate, but we want the same "now" with each page. 
      var rights = session.Query<RightsDeclaration>() 
           .Customize(x => x.WaitForNonStaleResultsAsOf(now)) 
           .Where(x => x.ScreenRights.Any(y => y.ScreenId == screenId)) 
           .Skip(page * pageSize) 
           .Take(pageSize) 
           .ToList(); 

      foreach (var right in rights) 
      { 
       // Remove the screen from any rights that used it 
       right.ScreenRights.RemoveAll(x => x.ScreenId == screenId); 

       // You might want to delete any empty rights declarations 
       if (right.ScreenRights.Count == 0) 
        session.Delete(right); 
      } 

      // Exit when we get back less than a full page, indicating there are no more pages. 
      if (rights.Count < pageSize) 
       break; 

      // Next page please. 
      page++; 
     } 

     // Delete the screen. 
     session.Delete(screen); 

     // Save all your changes together. 
     session.SaveChanges(); 
    } 
} 

另一種方法是使用Raven的Patching API執行更新。速度更快,但您沒有交易保證。

你也可以看看Raven的Cascading Deletes Bundle,但我不認爲它會在這裏工作,因爲你不一定每次都刪除RightsDeclaration

更新

予壓出一些較硬尋呼碼的成易於消耗擴展方法。這現在是ravendb/contrib項目的一部分。利用這些擴展,你的代碼簡單得多:

using (var session = documentStore.OpenSession()) 
{ 
    var screen = session.Load<Screen>(screenId); 
    if (screen != null) 
    { 
     // Get all rights that use this screen. 
     session.Query<RightsDeclaration>() 
       .Customize(x => x.WaitForNonStaleResultsAsOfNow()) 
       .Where(x => x.ScreenRights.Any(y => y.ScreenId == screenId)) 
       .ForEachWithPaging(right => 
        { 
         // Remove the screen from any rights that used it 
         right.ScreenRights.RemoveAll(x => x.ScreenId == screenId); 

         // You might want to delete any empty rights declarations 
         if (right.ScreenRights.Count == 0) 
          session.Delete(right); 
        }); 

     // Delete the screen. 
     session.Delete(screen); 

     // Save all your changes together. 
     session.SaveChanges(); 
    } 
} 
+0

哦!馬特,這是一個很好的解決方案。它完美無缺。+ 100。我還需要一個幫助請給我簡短的解釋,或者參考一些文檔解釋你在查詢中做了什麼。對不起,如此愚蠢我不知道爲什麼頁面,頁面大小,現在都在這裏使用,這就是爲什麼我問它。 – user1811801

+0

作爲「默認安全」原則的一部分,Raven限制了返回的查詢結果的數量。如果你沒有指定.Take(),它會在128個結果中將你截斷。如果你指定了一個,你不能比Raven/MaxPageSize設置更高,除非你改變它,否則它是1024。評論http://ravendb.net/docs/client-api/querying/paging和http://ravendb.net/docs/intro/safe-by-default –

+0

另外 - 如果你有大量的RightsDeclaration類(> 1024 * 30),您可能會遇到可在單個會話中進行的請求數限制。我在更新中引用的擴展方法考慮到了這一點,並進行了適當的調整。 –