Specification Pattern with Navigation Properties - c#

Is it correct to use Specification Pattern with Navigation Properties ?
I have the follow context:
When I add a student, I need to validate the addresses.
Student class:
public class Student {
public string Name { get; set; }
public DateTime Birth { get; set; }
//...
public virtual ICollection<StudentAddress> StudentAdresses { get; set; }
}
StudentAddress class:
public class StudentAdress{
public int Id { get; set;}
public string Street { get; set; }
//...
}
On my student service (DDD):
Service:
public void AddStudent(Student student)
{
// code
var studentValidation = new StudentValidation().Validate(student); // Student Validation has a set of specifications that will populate a validation result object and that I'll retrieve it by Domain Controller Notification (MVC)
// code
}
PS: Student Validation has a set of specifications that will populate a validation result object and that I'll retrieve it by Domain Controller Notification (MVC)
Back to the question...
Where may I put my Student Addresses class specifications ?
I thought of the possibility of putting them inside StudentValidation class and there use the Navigation property to be able to validate each address. I do not know if that is correct. It would be a type of transversal validation.

In DDD, validation is a form of ensuring invariants are met. This is the responsibility of the Aggregate Root in an Aggregate. In your example, perhaps Student is the root of the Student Aggregate, with StudentAddress as a child. In that case, it makes sense for Student to be responsible for ensuring the aggregate is in a valid state. Ideally, the logic for this should literally live inside of the Student class itself, but in your case you appear to be using a StudentService to perform validation of Student. So, in your case, it would be fine and proper (IMO) to perform the address validation from StudentService, since it's essentially taking on the responsibility of your aggregate root.
Whether or not you need separate validator types for StudentAddress than for Student depends on the context/scope of the validation rule in question. For example, if you must validate that an Address includes a City, that's easily done at the StudentAddress level. However, if you need to validate that a Student has at least one Address, or that a Student doesn't have two duplicate Addresses, that would need to be done at the Student level.
You can learn more about DDD in general here.

Related

Creating C# objects via MySQL

I would like to get help from you, please :-)
I'm thinking about good way for programmatically creating of classes in C# via MySQL database.
In my app I'm creating composite classes. For example Student, Classroom, Room (dormitory) and so on. Class Student contains properties Classroom and Room. ClassRoom is also related to another entities in database...
public class Student
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public Classroom Classroom { get; set; }
public Room Room { get; set; }
}
public class Classroom
{
public int Id { get; set; }
public string Title { get; set; }
public byte Level { get; set; }
public Teacher Teacher { get; set; }
}
...etc
Usually when I need create object of some class, I must create also another classes' objects (sometime a part of database :-) ).
I think this way is not good optimalized, BUT there are great OOP benefits. When I load all students in a DataGridView, I can manage lots of related parts... for example:
Student student = ...
string currentTeacher = student.Classroom.Teacher.LastName //... and so on.
Is OK to create all related classes' objects immediately or is better create only necessary data of current created object and another data load / create "on demand"?
Or absolutely different way? :-)
See, the idea is for you to make a query exactly like what you need an Ingress for a structural database like sql, talking a lot about the EntityFrame mappings where it is possible to query only the student object/table only by its id, however, if no process you will need the Classroom in which it belongs to you use a .Include() no entity and you would only be able to fetch the objects you will need in your request no problem mapping all entities as a bank into objects, the problem is to retrieve all of them from the relation since it only has a feature in some articles
https://learn.microsoft.com/pt-br/ef/ef6/querying/related-data
https://www.entityframeworktutorial.net/code-first/configure-entity-mappings-using-fluent-api.aspx
But if your purpose is performance, mount only the data you need in an object, just an example StudentInfo with the information you need grouped, use a Dapper to make the optimized query and make it do this mapping to your object, gaining performance
this is clear speaking of relational databases like Sql if your case is a NoSql database like MongoDb there is no problem in your mappings since it will return everything in a single document it is structured for this type of information there will be no InnerJoin cost between tables

Model relationships causes trouble with Swagger/endpoints

I have two entities, Classroom, and Student. One-to-many relationships and I use EF Core: one Classroom can have many Students, and one Student can be in one Classroom.
public class Classroom
{
public int ClassroomId { get; set; }
public List<Student> Students{ get; set; }
}
public class Student
{
public int StudentId { get; set; }
public string Name { get; set;
public int ClassroomId { get; set; }
public Classroom Classroom { get; set; }
}
To make this as short as possible I have left out Controller, DataContext, DbSet<> for tables, etc., but I have created it all.
Now, if I run my application and I want to POST a Classroom through Swagger, it includes the list of students in the model schema, so that I have to create the list of students as if it was a property that I wanted to create at the same time as I create a classroom. Similarly, if I want to create/POST a student, it includes the classroom in the model schema.
Instead, I want to be able to create a Classroom and Student separately. When I create a Student, I want to be able to specify only the Classroom Id, so that I can connect students to existing classrooms, not create them same time.
How do I go about this? I am sure I misunderstand something, so I appreciate all help I can get. Thanks
How do I go about this?
You do not expose your database models to the outside world. They are your database models, not your data exchange objects. Nobody but your ORM needs to see them or should see them, you can annotate them so your database layer will know what to do.
Your controller layer should have a set of model classes that you use to talk to the outside world via REST (using swagger). You can build them however you see fit, you can annotate them so your REST layer will understand what to do.
Then you need to map the models you get from the outside world to something you want to do with your database. That should be quite straightforward.

C# MVC: How to create model for multi step form?

I have multi step form where user completes university registration:
In first form, student fills his personal details. (Name, Email, Mobile)
In second form, student fills marks obtained in high school. (Percentage)
In third form, student fills his parents details. (Name, Email, Mobile)
This finally gets saved to database.
I have created three partial views for these forms.
Should I create 1 c# model class that has all these fields and use it across the three partial views?
OR
Create separate c# model classes for each of these views?
Please note that these form steps may have different layout/number of fields on different platforms like desktop,mobile,apps i.e. we are planning to combine step1 and step2 on desktop and keep them as separate steps on mobile & apps.
Do something Like
public class ViewModel
{
public basic BDetails{get;set;}
public Advanced ADetails{get;set;}
public Personal PDetails{get;set;}
}
public class basic{
.....
}
public class Advanced
{
....
}
public class Personal
{
......
}
use the ViewModel class as your View class
Separate Models and Database Tables.
I did a similar project for a secondary school and the original system was based on flat topography. There ended up being multiple children and redundant information as siblings were enrolled. The data was partially normalized into tables for families, students, schools, subjects and bridge tables to handle the 1:n and n:n relationships between them.
While this took a little longer to implement, it was easier when the system was enhanced to be more user friendly. Schools were pre-populated and able to be selected in a list; the same was done with subjects. Addresses were standardized to conform with post office specifications.
The end result was a very happy client. Besides uniformity of the information, duplicate emails and postal mailings were heavily reduced. They also contracted for further work to add in demographic reporting and identify their recruiting weaknesses and strengths. They contracted with a sister company for marketing too.
First off: I would suggest that you use one model for student and parent(since they have similar properties - Name, Email, Mobile). You could make a Person model and it could have the enum PersonType. PersonType should be Student or Parent:
public class Person
{
public int PersonId { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Mobile { get; set; }
public PersonType Person { get; set; }
}
enum PersonType
{
Student,
Parent
}
Next off: only one view is necessary in your case. Use a ViewModel as the model for it. The ViewModel could look something like this:
public class VMStudentDetails
{
public float Percentage { get; set; }
public Person Student { get; set; }
public Person Parent { get; set; }
}

DTO naming conventions , modeling and inheritance

We are building a web app using AngularJS , C# , ASP.Net Web API and Fluent NHibernate.
We have decided to use DTOs to transfer data to the presentation layer ( angular views).
I had a few doubts regarding the general structuring and naming of DTOs.
Here's an example to illustrate my scenario.
Lets say I have a domain entity called Customer which looks like:
public class Customer
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual Address Address { get; set; }
public virtual ICollection<Account> Accounts { get; set; }
}
Now, in my views/presentation layer I need to retrieve different flavors of Customer like :
1) Just Id and Name
2) Id , Name and Address
3) Id , Name , Address and Accounts
I have created a set of DTOs to accomplish this :
public class CustomerEntry
{
public int Id { get; set; }
public string Name { get; set; }
}
public class CustomerWithAddress : CustomerEntry
{
public AddressDetails Address { get; set; }
}
public class CustomerWithAddressAndAccounts : CustomerWithAddress
{
public ICollection<AccountDetails> Accounts { get; set; }
}
AddressDetails and AccountDetails are DTOs which have all the properties of their corresponding Domain entities.
This works fine for querying and data retrievals ; the question is what do I use for inserts and updates. During creation of a new customer record , name and address are mandatory and accounts are optional ..so in other words I need an object with all the customer properties. Hence the confusion :
1) What do I use for insert and updates?
The CustomerWithAddressAndAccounts DTO has everything in it but its name seems a bit awkward to be used for insert/updates.
2) Do I create another DTO .. if I do , wouldn't that be duplication as the new DTO will exactly be like CustomerWithAddressAndAccounts ?
3) Last but not least , does the DTO inheritance strcuture described above seem like a good fit for the requirement ? Are there any other ways to model this ?
I have gone through other posts on this topic but couldn't make much headway.
One thing that I did pickup was to avoid using the suffix "DTO" in the class names.
I think it feels a bit superfluous.
Would love to hear your thoughts
Thanks
Recommendation is that you should just have one DTO class for each entity suffixed with DTO e.g. CustomerEntryDTO for the Customer entity (but you can certainly use inheritance hierarchies as per choice and requirements).
Moreover, Add a abstract DTOBase kind of base class or an interface; and do not use such deep inheritance heirarchies for each Address, Account and other properties to be included in child DTOs. Rather, include these properties in the same CustomerEntryDTO class (if possible) as below:
[Serializable]
public class CustomerEntryDTO : DTOBase, IAddressDetails, IAccountDetails
{
public int Id { get; set; }
public string Name { get; set; }
public AddressDetails Address { get; set; } //Can remain null for some Customers
public ICollection<AccountDetails> Accounts { get; set; } //Can remain null for some Customemer
}
Moreover, your DTOs should be serializable to be passed across process boundaries.
For more on the DTO pattern, refer below articles:
Data Transfer Object
MSDN
Edit:
In case you don't want to send certain properties over the wire (I know you would need to that conditionally so would need to explore more on this), you can exclude them from the Serialization mechanism by using attributes such as NonSerialized (but it works only on fields and not properties, see workaround article for using with properties: NonSerialized on property).
You can also create your own custom attribute such as ExcludeFromSerializationAttribute and apply it to properties you don't want to send every time over wire based on certain rules/conditions. Also see: Conditional xml serialization
Edit 2:
Use interfaces for separating the different properties in the one CustomerEntryDTO class. See the Interface Segregation Principle on Google or MSDN. I will try to put a sample explanation later.
What do I use for insert and updates?
Service operations are usually defined in very close relation to business operations. Business language doesn't speak in terms of "inserts" and "updates", neither do services.
Customer management service is likely to have some Register operation that takes customer name and maybe some other optional parameters.
Do I create another DTO?
Yes, you should create another DTO.
Sometimes service operation contract may be enough and there is no need to define a separate DTO for a particular operation:
function Register(UserName as String, Address as Maybe(of String)) as Response
But most of the time it is better to define a separate DTO class even for only a single service operation:
class RegisterCommand
public UserName as String
public Address as Maybe(of String)
end class
function Register(Command as RegisterCommand) as Response
RegisterCommand DTO may look very similar to CustomerWithAddress DTO because it has the same fields but in fact these 2 DTOs have very different meanings and do not substitute each other.
For example, CustomerWithAddress contains AddressDetails, while a simple String address representation may be enough to register a customer.
Using a separate DTO for each service operation takes more time to write but easier to maintain.
As of your item 1, for inserts and updates it's better to use Command pattern. According to CQRS, you don't need DTOs. Consider this schema:
via blogs.msdn.com

Entity Framework Code First optional one-to-one relationship with no reverse navigation property

I am trying to model what I think is quite a basic scenario, but I can't get my head around the correct way to define it in EF Code First 5.
I have three classes:
Employee
Postal Address
Contact Telephone Number
The rules are thus:
A Postal Address can be standalone
A Contact Telephone Number can be standalone
Optionally, an Employee can have a "Home" Postal Address
An Employee can have zero or more Contact Telephone Numbers
If I model this in SQL, I end up with four tables;
PostalAddress
ContactTelephoneNumber
Employee
EmployeeContactTelephoneNumber (bridge table)
By looking through the answers here on SO, I can produce something similar to my SQL model in Code First with the exception that I have to have an Employee navigation property on PostalAddress and an Employees navigation property on ContactTelephoneNumber. This goes against my business rules, because neither PostalAddress nor ContactTelephoneNumber will always be refered to be an Employee. For example, I could later add a Premises class which would also have a PostalAddress.
By way of code examples, what I have now resembles the following:
public class Employee
{
public int EmployeeID {get;set;}
public virtual PostalAddress? HomeAddress {get;set;}
}
public class PostalAddress
{
public int PostalAddressID {get;set;}
public string Address {get;set;} // It's not actually a string - this is for brevity!
}
public class ContactTelephoneNumber
{
public int ContactTelephoneNumberID {get;set;}
public string TelephoneNumber {get;set;} // It's not actually a string - this is for brevity!
}
I'm trying to define my relationships using the Fluent API rather than Annotations, to ensure my presentation layer remains unaware of Entity Framework when consuming these classes. My mapping currently resembles the following - is this "correct"?
public class EmployeeMap : EntityTypeConfiguration<Employee>
{
public EmployeeMap()
{
this.HasOptional(e => e.HomeAddress).WithOptionalDependent(p => p.Value).Map(m => m.MapKey("PostalAddressID"));
}
}
This doesn't compile; I get:
The type 'PostalAddress?' must be a reference type in order to use it as parameter 'TTargetEntity' in the generic type or method 'System.Data.Entity.ModelConfiguration.EntityTypeConfiguration.HasOptional(System.Linq.Expressions.Expression>)'
Additionally, I don't like that I'm passing "PostalAddressID" as a string constant into the call to MapKey().
Please could someone highlight the error of my ways? I've been searching for the past 3 hours to no avail!
Edit: I should mention that once I understand this part I'll try and address the Employee>ContactTelephoneNumbers situation separately.
You have declared HomeAddress as a value type, specifically as a Nullable<T>.
Remove the ? from the declaration (reference types allow null, and therefore do not need to be wrapped in the Nullable struct).
public virtual PostalAddress HomeAddress {get;set;}
To specify the mapping, I think you can use this:
this.HasOptional( e => e.HomeAddress ).WithMany().HasForeignKey( e => e.HomeAddressID );
You will also need to add the HomeAddressID property to the Employee class.

Categories