I have two conceptual entities: Employee and Mailbox.
Employee is associated with 0,1..n Mailboxes.
There are two associative roles "owner" and "reader".
In the underlying SQL database, there is a link table called MailboxView that links theEmployee and Mailbox tables and has an intersection data column of "Role".
In the EF entity model, this link table is represented as data entity because there is an intersection data column - hence 3 EF entities:
Employee --> MailboxView <-- Mailbox
The relevant use-cases are:
1. An Employee can read and change Mailboxes for which their Role="owner"
2. An Employee has read-only access to Mailboxes for which their Role="reader"
Can anyone suggest the simplest pattern of business objects which implement this behaviour?
Can I, for example, have two collection objects - OwnerMailboxes, which is an ECC and ReaderMailboxes which is a ROC - both having Mailbox as items? I could use join queries on the entity model (per Julia Lehrman's article at: http://learnentityframework.com/LearnEntityFramework/tutorials/many-to-many-relationships-in-the-entity-data-model/
Is there a better pattern?
I vote against your plan to use the Mailbox child class in both the ECC and the ROC. Rocky has stated many times that the fact that two objects have many of the same properties is not a good enough reason to try to "re-use code". I agree.
I agree that an Employee object should have two collections as you named them. And that they should be an ECC and an ROC.
The ECC should have an editable child BO named Mailbox.
But the ROC should have an internal class named MailboxInfo which has Public Get and Friend Set methods for each Property. It should also have 2 constructors:
Private Sub New()
'require use of factory methods
Friend Sub New(ByVal dr As SafeDataReader)
mCode = Trim(.GetString("code"))
The Friend constructor is used by the ROC to populate each instance of the Info class.
RaiseListChangedEvents = False
IsReadOnly = False
Dim dr As SafeDataReader = Nothing
Dim strSQL As String = "someSQL"
dr = New SafeDataReader(DAL.ExecuteReader(strSQL))
Dim info As New someInfo(dr)
Catch ex As Exception
Throw New ApplicationException("Exception in myList DataPortal_Fetch.", ex)
If dr IsNot Nothing Then dr.Close()
IsReadOnly = True
RaiseListChangedEvents = True
Normally I'd agree, but in this case it seems like a case where you're opening a detail screen to which you only have readonly access. For example, in my system a user might be able to view everything about an Order, but never be able to edit it. I don't see a reason to create an identical screen, with an identical (but readonly) BO just to display the data.
The MailBox class could have an OwnerId property, and its only a few lines of business code which determines access, readonly or read / write.
If this is the same screen, and same object, with different authorization based on the user and object state, then it seems like the solution is to use the authorization subsystem?
Override CanWriteProperty() and return false if the user isn't authorized to manipulate the object? And override Save() to throw an exception if they try to save?
Is this question directed at me, or the OP?
Thanks to all who provided feedback on this one.
I think that approaching this as an authorization issue will work best for me. My OP failed to point out that Mailbox have Folders, Folders have Folders, Folders have Messages etc. etc. I need to provide a view of the entire structure that differs only in accessibility, based on the relationship between the Employee and a particular Mailbox. While I need to prototype this a bit further and see, for example, how CanWriteProperty is (or isn't) propagated to child objects, it seems more promising to take the tack suggested by Rocky.
Copyright (c) Marimer LLC