Specialization of a Weak Entity in ER Diagram Modeling - entity-relationship

I've been making ERD for quite some times but, I encountered a unique case now as follows*:
Every Account may do a Registration
Every Registration requires Acceptance Period
Every Registration requires at least 1 Program or more
There are 2 kinds of Registration, UUI Registration and SEMAS UI Registration. A Registration can either be UUI Registration or SEMAS UI Registration but it can't be both (disjoint)
SEMAS UI Registrasion must be either a SEMAS S1 Registration, SEMAS S2 Registration or SEMAS S3 Registration (disjoint).
UUI Registration and SEMAS S1 Registration records the registrant Prior School
SEMAS S2 Registration and SEMAS S3 Registration records the registrant Prior University
From the description we know that Registration is a weak entity as it cannot exist without Account, Acceptance Period and Program. But Registration has specializations here.
So the question is:
Am I allowed to model UUI Registration and SEMAS UI Registration as subclasses of Registration which is a weak entity?
If it is allowed, how do I model them? As weak entities too or as strong entities?
Thank you for all of your help!
*Ignore attributes

While weak entity sets have an existence dependency on their parent entity sets, existence dependencies don't automatically mean an entity set is a weak entity set. A regular entity set can be required to participate totally in a relationship, which similarly imposes an existence dependency.
To identify weak entity sets, look at how they're identified. A weak entity set's identity / primary key will be a superset of its parent's identity / primary key.
There's no restriction to prevent weak entity sets from having subtypes. However, I haven't seen any examples of how to represent them on ER diagrams. I'm inclined to draw them in the same way as their parent entity sets (i.e. as weak entity sets) since they have the same identity. Another reason is that in classic ER (before EER notation for subtyping), the only way to represent a subtype was as a weak entity set without a weak key.

Related

How do I define two types of users in .NET Identity that each have different properties?

I'm using .Net Identity and I have different types of users (RegualrUser, OrganizationUser). Both of them are users.. that is, they can log in to my site.
I want to save additional information for each type, and that information is different, meaning that the first type, RegualrUser, has different properties than the second type, OrganizationUser.
Here in this answer User Claims are recommended. In fact, I am not convinced... because it is possible that these different properties are not just a value and type, but may be a relationship to another table in the database (a navigational feature).
Plus the User Claims are a difficult part for me, i didn't get what is difference between (User Claims, Identity Claims, Claims principal).
I tried to inherit from IdentityUser twice, once for the first type and once for the second. And then adding those types through the AddIdentityCore method, but it became after migration the properties were put together in the AspNetUser table, meaning Table per Hierarchy.

Validity of domain entity method based on context or caller

I am currently reading about DDD and have a issue how to implement a certain validation.
Scenario:
I have an entity Group that contains a list of Members which in turn consists of a User and a MemberState (Member, Admin). The entity has a method MakeAdmin(User user) that turns a member into an admin.
The rule is: Only if the current user is admin of the group, it is allowed to turn the member to an admin.
I have three possible implementations in mind, with some caveats each.
Variant 1
Group enitity gets a dependency IUserContext injected via constructor to get the current user. With that the entity can check if the current user is admin and is allowed to switch the member state.
Caveat: I don't like that the domain entity has such a dependency injected and I don't think that is correct in a DDD view.
Variant 2
Method MakeAdmin() gets an additional parameter which turns it into MakeAdmin(User user, User currentUser). That removes the requirement for the IUserContext dependency in the entity.
Caveat: I am not sure if it is correct at all that the entity validates this rule, because it is not really an invariant of the entity.
Variant 3
Validate this rule in an application service, and only call MakeAdmin(User user) if validation passed.
Caveat: I consider the rule domain specific, so I think it is not correct to put it in application layer.
So what would be the best option, or is there some totally different variant?
My suggestion would be to go with your third option: Authorise access in the application/integration layer and then call into the domain.
This goes for any domain functionality really. The domain should not concern itself with whether the action may or may not be performed based on authorisation but rather only with domain concerns. If that authorisation action happens to be a domain concern in a particular Identity & Access Control bounded context that it would make sense but you would not run into those too often.

Is it ok to have database context in my domain model

I am developing a web based application using ASP.NET MVC. I am trying have rich domain models rather than the thin/anemic models.
I have modelled my solution along the lines of Onion architecture. The different projects are as below :
{}.Domain.Core - contains the domain objects and interfaces like IDbContext which is implemented in the Infrastructure layer
{}.Database - is the database prject
{].Infrastructure - contains implementation for logging, Data Access etc.
{}.Web - View and Controllers
**** The data access is done using dapper and IDbContext is a wrapper around 2 simple command, query interfaces. I have isolated each of the queries as separate class.
For sake of discussion I am taking a small part of the application.
I have a versioned document library which contains documents along with other metadata like tags, permissions etc
A simplified model of my document object is as shown below
I would want the operations to be defined within the domain object, since there is business logic involved in each of these operations.
Let me take "Delete" as an operation. The operation needs to be perform
Validate if user has permission to delete
Check if there are no associations which will get impacted by this delete
Check if no workflow is in progress
Delete the actual item from database in a transaction
As shown in above example, I would need the database context to complete this operation.
The way I have currently thinking if modeling is to have the domain object have IDbContext, which can execute the queries exposed.
In my controller class I call the domain objects and perform the operations.
I am not sure if passing the IDbContext in the domain object is ok? If not what are the better ways to model this?
I am not convinced in having a separate service layer because
1) Controller act as first layer of service layer for most of the cases
2) Service layer is just duplicating the same methods from domain to another class
Let me know how I can better this design.
Injecting the IDbContext like that brakes the main principle of the Domain model which should be responsible for business logic ONLY while retrieving and storing your domain entities is the responsibility of the infrastructure layer. Yes you inject it by interface, hiding the actual implementation but it makes you domain model aware of some storage.
Also the steps from above required to delete a Document doesn't entierly belong to the Document object. Let's consider the first step with user permissions and the following cases:
Users with Admin role should be allowed to delete any document
Document owner should be allowed to delete the document
For the first case there might not be a connection between a user and a document to remove. Admin users are just allowed to do anything. It's like a classical example with two bank accounts and an operation to tranfer money which involves both accounts but is not their responsibility. This is when Domain services come into place. Please don't confuse them with Service layer services. Domain services are part of the domain model and responsible for business logic only.
So if I were you, I would create a new Domain service with DeleteDocument method. This should do the first three steps from above accepting User and Document as parameters. The fourth step should be done by your repository. Not sure what you mean by saying
I didn’t see too much value in adding repositories
but from domain model perspective you already have one it's the IDbContext. I assume you meant some pattern to implement repository or separate repository for each entity. In the long run your pseudo code in the controller should be the following:
var user = bdContext<User>.SelectById(userId);
var document = bdContext<Document>.SelectById(docId);
var docService = new DocumentService();
docService.DeleteDocument(document, user); // Throw exception here if deletion is not allowed
bdContext<Document>.Delete(document);
If you expect you need this logic in many places of you application you can just wrap it up in a Service layer service.
I suggest reading Eric Evans book on DDD if you want to learn more about Domain modeling. This discusses the meaning of entities, value objects, domain services, etc. in detail.
ANSWER TO THE COMMENT:
Not really, the domain services are part of the domain, so both implementation and interface are part of the domain as well. The fact that two or more objects have to interact with each other is not enough for creating a domain service. Let's consider a flight booking system as an example. You have a Flight entity with different properties such as DepartureCity, ArrivalCity. Flight entity should also have a reference to a list of seats. Seat could be a separate entity as well with such
properties as Class (business, economy, etc.), Type (isle, row, middle), etc. So booking a seat requires interacting with different entites, such as Flight and Seat but we don't need a domain service here. As by nature Seat property makes no sense if not considered as a child object of a Flight. It's even very unlikely you would ever have a case to query a Seat entity from out of the Flight context. So reserving a Seat is responsibility of the Flight entity here and it's ok to place the reserving logic to the Flight class. Please note it's just an example to try and explain when we need to create domain services, a real system could be modeled completely another way. So just try following these three basic steps to decide whether or not you need a domain service:
The operation performed by the Service refers to a domain concept which does not naturally belong to an Entity or Value Object.
The operation performed refers to other objects in the domain.
The operation is stateless.
I'm accessing dbcontext from the controller which is application/service layer not domain/business layer. Domain model deals with business logic only, it should not be aware of any persistance logic and from the example above you can see that DocumentService has no references of the dbcontext.

ASP.net MVC: Where in my design should I create/declare entity keys?

When creating a new entity object that has a foreign key value I need to create a new Entity key (Entity Framework in .net 3.5) for the object, but I'm having trouble deciding where in my application I should do this.
Right now when I create a new record with a foreign key, I create the entity key in the controller (in this case a user ID pulled from a membership provider), assign it to the object and pass it to the repository service layer.
Are there any problems with this, or should I be passing the object plus the user ID to the repository service layer and have it deal with the entity key creation? Passing one object seems cleaner, but having multiple controllers assigning keys this way makes me nervous. Thanks.
I think this is a matter of separation of concerns. A repository is concerned with retrieving and adding/changing/removing entities. It shouldn't be responsible for building entities. Conversely, the controller really shouldn't be responsible for building entities either (a controller should to the bare-bones amount of work required to push data to a view, and handle commands from a view delegate those commands to business logic...business logic belongs elsewhere (like a domain).) In all honesty, you should create an EntityBuilder of some sort to handle the process of creating entities. You would pass the object plus user ID to a builder, which would then provide you with a fully built entity that could then be passed on to a repository.
EDIT:
Even with your change from 'Repository' to 'Service Layer', the principal remains the same. Delegate the process of building your entity to a dedicated builder, and maintain your separation of concerns.

Do roles/views belong inside or outside of the Repository Pattern?

Does role / view logic belong inside or outside of the Repository Pattern?
For example, I have a table of products, and each product has 5 price fields - one for each type of customer (wholesale, retail etc).
I only want to show the appropriate price to the appropriate user.
If I have a repository of these products, should the Product business object returned, contain all 5 prices, and somehow only display the relevant price?
If so, what is a good pattern to use?
Should I perhaps create a view object, which takes a business object and a role and determines the right price to show? Or shall I put that logic inside the business object?
(FYI: I will be building the solution in ASP MVC if you think it will help frame the response)
Yes, your repository should return all five prices, and your objects should contain the business logic that decides which customer receives which price. The objects should be capable of making this decision regardless of where their data came from.
This approach will also allow you to test your pricing logic independently of your data access concerns - for example, by using a 'dummy' repository, by manually creating a product with the five price fields already populated, or by using a mocking framework to mock your repository calls. Moving this sort of logic outside your business objects - e.g. putting it in your data access layer - can lead to an anti-pattern known as the Anemic Domain Model.
EDIT: In response to your comments:
The term "repository" specifically refers to a data access pattern that returns fully-populated collections (aggregates) of business objects. If you find that returning DTOs is a better solution for your problem, then go ahead and do so, but you may confuse people if you use the term "repository" to refer to other data access patterns. Personally, I'd stick with the repository approach and return fully-populated business objects, because I prefer working that way, but as with so much, it depends on the scale and complexity of the system you're building.
To expose your pricing logic, you probably just want to use a method like:
public class Product {
public decimal GetPriceFor(User user) {
// logic to determine per-user pricing goes here:
}
}
One approach is to create a service layer that contains your business logic. The service layer interacts with the repository applying any rules or filters that you require. This means anything returned from the service layer is just a plain c# object (POCO).
After designing some products with an extra data access layer, I would say: Design it with the functional dependencies in mind!
Suppose you have the following very common structure for the data dictionary: productName, productDetail, productPrice, customerName, customerDetail.
One can easily identify the relations: Customer and Product.
class Customer: customerName, customerDetail
class Product: productName, productDetail
But there is a third relation to draw, it is
class CustomerProduct: customerName, productName, productPrize
Because you can reason that only customerName X productName |-> productPrize. For the use case Customer C wants to know the price of product P:
Customer('C').prize('P')
The method prize must be delegated to know the exact prize and you have a clean separation of concerns. To be clear about the point: the BO will show no prize to the customer. Just the method has access to the delicate data. And this access you can restrict.

Resources