2014-06-20 53 views
1

說我有以下對象樹。我的對象樹是不是真的這個愚蠢的,但它確實有許多許多一對多的關係保持複雜對象樹中的對象同步

Account 
- Users {UserId, Name, etc} 
- UserPermissions {User object, Permission object} 
- Permissions {PermissionId, Name, etc} 

說,我想刪除一個用戶或從賬戶對象下一個權限對象。我希望在任何情況下,任何包含已刪除項目的UserPermission對象也將從UserPermission集合中刪除。

有沒有這樣做的優雅方式,而無需手動刪除UserPermission對象?我知道來自實體框架模型的對象做到這一點,但不知道如何實現相同的結果......我沒有使用EF,而是將對象結構保存到RavenDb。

每請求時,這裏是一個更全面的數據模型

public class Account 
{ 
    public List<User> Users {get;set;} 
    public List<UserGroup> UserGroups {get;set;} 
    public List<Alert> Alerts {get;set;} 
    public List<Resource> Resources {get;set;} 
    public List<AlertSubscription> AlertSubscriptions {get;set;} 
} 
public class UserGroup : IAlertSubscriber 
{ 
    public string Name {get;set;} 
    public List<User> Users {get;set;} 
} 
public class User : IAlertSubscriber 
{ 
    public string Name {get;set;} 
} 
public class AlertSubscription 
{ 
    public Alert Alert {get;set;} 
    public List<Resources> AlertPublishers {get;set;} 
    public List<IAlertSubscribers> AlertTargets {get;set;} 
    public int MinimumSeverity {get;set;} 
} 

所以,我很想能夠做的是,如果我刪除Account.Users收集用戶,也核彈它來自各種AlertTargets,UserGroups等。如果我從Account.UserGroups中刪除UserGroup,我想從AlertTargets中將其刪除,如果我從Account.Resources中刪除資源以從它中刪除AlertSubsciptions ...

回答

1

而不是試圖同步兩個相同數據的副本,我會去單一副本。您可以只擁有UserPermissions列表,並計算其他兩個集合:

public class Account 
{ 
    private List<UserPermission> _userPersmission; 

    public List<UserPermission> UserPermissions 
    { 
     get { return _userPersmission; } 
     set { _userPersmission = value; } 
    } 

    public IEnumerable<User> Users 
    { 
     get { return _userPersmission.Select(up => up.User); } 
    } 

    public IEnumerable<Permission> Permissions 
    { 
     get { return _userPersmission.Select(up => up.Permission); } 
    } 
} 

或計算基於其他兩個集合的UserPermissions。但我更喜歡以前的方法,因此UserPermission可以有額外的數據。

更新:如果您不能計算所有集合中的某些集合而沒有重複數據,那麼您將回到Observer。您的案例中的主題是不同的集合,如用戶。如果某些項目被刪除,主題應該通知其他收藏。 BindingList<T>是實現這種通知的主題。遺憾的是它並沒有提供有關其已刪除項目的信息,所以你需要創建自定義綁定列表:

public class ExtendedBindingList<T> : BindingList<T> 
{ 
    public T LastRemovedItem { get; private set; } 

    protected override void RemoveItem(int index) 
    { 
     LastRemovedItem = base[index]; 
     base.RemoveItem(index);    
    } 
} 

你可以用它來獲取有關項目的通知移除:

public class Account 
{ 
    public ExtendedBindingList<User> Users { get; private set; } 

    public Account() 
    { 
     Users = new ExtendedBindingList<User>(); 
     Users.ListChanged += Users_ListChanged; 
    } 

    private void Users_ListChanged(object sender, ListChangedEventArgs e) 
    { 
     if (e.ListChangedType != ListChangedType.ItemDeleted) 
      return; 

     foreach (var group in UserGroups) 
      group.Users.Remove(Users.LastRemovedItem); 
    } 

    // ... 
} 

另一種選擇是使用方法AddUserRemoveUser修改用戶列表。並公開用戶列表IEnumerable

public class Account 
{ 
    private List<User> _users = new List<User>(); 

    public IEnumerable<User> Users { get; } 

    public void AddUser(User use) 
    { 
     _users.Add(user); 
    } 

    public void RemoveUser(User user) 
    { 
     _users.Remove(user); 

     foreach (var group in UserGroups) 
      group.Users.Remove(user); 
    } 

    // ... 
} 
+0

只要還有另一個涉及用戶或權限的多對多關係,它會崩潰嗎? – Igorek

+0

@Igorek很高興看到反映您真實問題的樣本 –

+0

已更新的問題。感謝幫助! – Igorek