Creating C# objects via MySQL - c#

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

Related

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.

MVC Complex Model Binding to List<T>

I am a new noob at c# MVC and I would really like some help if possible or if someone could kindly point me in the right direction. I have spent hours and hours looking for a solution online and I am yet to find anything helpful which is why I am posting here.
I am working on creating an employee database web application for my company and I have for example the following classes.
namespace my_app.Models.Employee
{
public class Employee
{
public Employee()
{
}
// id
public int id { get; set; }
// employee id/payroll no
public string Employeeid { get; set; }
// employee qualifications
public IList<EmployeeQualification> EmployeeQualifications { get; set; }
}
}
namespace my_app.Models.Employee
{
public class EmployeeQualification
{
public EmployeeQualification()
{
}
// employee Qualification id
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
// employee Qualification institution
public string Institution { get; set; }
// employee Qualification qualificaiton
public string Qualification { get; set; }
public IList<Employee> Employees { get; set; }
}
}
The employee is being added to an EmployeeViewModel which looks something like this:
namespace my_app.ViewModels
{
public class EmployeeViewModel
{
public Employee Employee { get; set; }
// more stuff here
}
}
Now the problem I have and that I need help with is I would like to display the employee (i.e. Name, Address etc) in a view but also be able to list out the employee's qualifications with the ability to add and delete qualifications.
I have seen lots of tutorials out on the web of how to do this via AJAX and Entity framework SaveChanges method and i am sure that will work but the slightly complicated part with what i want to do is that i would like for the changes to remain on the client and only when the whole form including any changes to the employee object is submitted then the changes are persisted to the database.
Is there any way to do this with standard mvc controls or do i have to write a ton of JavaScript to save the changes to a local array of objects and then on the form submit append the additional form data.
I did write a whole bunch of jQuery to kind of get it to work but the issue is that I need to have this functionality on multiple views of the application and to have to write that much code each time does not seem smart.
Any help would be greatly appreciated, thanks.
Hope I can give you a direction to move forward.
Firstly, you need to change your Models design. Basically, 1 employee can have many qualifications and 1 qualification can owned by many employees. So you have many-to-many relationship here. Which means you need 3 models (Employee, EmployeeQualification, Qualification). The 2nd model will hold foreign keys to employee and qualification.
Next thing is UI, you want to keep all changes in UI before doing only 1 submit to persist data. That's actually a very good idea in term of user friendly system design. To do this, you just need to maintain a list of SelectedQualificationIds. Then keep that list in a hidden field, so after submitting, you can just load all qualitifications from DB, compare with the list, and remove/add qualification accordingly.

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; }
}

Domain Design crossing Aggregate Root Boundaries

I'm a novice DDD'er and struggling with my first attempt to implement some of these concepts. I am writing an application to manage some marketing campaigns for different users, so a Campaign is an obvious aggregate root, but I also have Users as an aggregate root.
public class Campaign : IDomainObject
{
public virtual int CampaignId { get; set; }
public virtual string Name { get; set; }
...
public virtual int UserId { get; set; }
...
public virtual IList<CampaignEvent> Events { get; set; }
}
public class CampaignEvent
{
public virtual int CampaignEventId { get; set; }
public virtual int CampaignId { get; set; }
public virtual int UserId { get; set; }
...
}
So now when I search for a list of campaigns to display, how do I get the User's name from the Id?
If I design the model with a database-agnostic perspective, I would add a UserName string to both objects and develop from there. However, I have to be practical and consider how this will eventually go back-and-forth to the database, and it doesn't appear that this new model will work with the ORM (presently NHibernate, but I don't believe this is possible with EF either).
What are some meet-in-the-middle solutions that will accomplish the goal of getting some user information available in the object, without compromising the concepts of DDD?
I think the key here is that you want to change the thought process to entity to entity or value object relationships.
In the way you are modeling your classes, you have a UserId as a property and are talking about it as if it was a relationship. I think what you are wanting to convey is a relationship between the Campaign and a User, a CampaignEvent and a User, etc. It is perfectly acceptable for a Campaign to be an Aggregate Root and a User to be an Aggregate Root. When you search for a campaign, it will have a relationship to a User, so how you get the name is by getting the Name from the User entity. We don't want to speak about Id's alone, as this breaks our representation of the real entity we are trying to model. So a campaign has a/a collection user/users, and a user has a/a collection of campaign/campaigns, as opposed to a campaign has a userid.
If you would like to display the user name from some result set that you got from your ORM/domain model then this is a somewhat of a problem. You should not query your domain model. So how to do it then?
Well, you should try to incorporate a query/read model. A very simple query layer should be developed. To get the data, you have a couple of options. You probably want to opt for some denormalisation along the way. You could add the user id and name as a value object to your aggregate so that it is stored in your transactional store. Your query would be able to access that and have the data readily available; else your query side would need to do a join.
You could also go with eventual consistency via a truly read-specific store that contains view-specific tables.
This approach will probably bring up some more questions but it really is not as cumbersome as it may appear.

How to deal with C# object references in MongoDB?

I'm wondering how to handle when an object is used in multiple locations. Given th following code (just example code) :-
public class Group
{
public ObjectId Id { get; set; }
public string Name { get; set; }
public List<Person> People { get; set; }
public List<Meeting> Meetings { get; set; }
}
public class Meeting
{
public string Subject { get; set; }
public List<Person> Attendees { get; set; }
}
public class Person
{
public string Name { get; set; }
}
If I store the group as a mongodb document, it will serialize all the people and meetings. However the same Person object can be refered to in the People List and as an attendee of a meeting. However once serialized they become separate objects. How can I maintain that the same "Person" object is both in the People list and Meetings list?
Or is there are better way to model this? One thing that could be done is put the "People" in a separate Document and embeded / reference it? This then starts to create more and more separate collections, ideally I'd like to maintain references within a single document.
Or within a document should I Id each person and have one master list and then only store lists of Ids in the "Meetings" and use some kind of helper method to resolve the Id from the master list? Can be done, but a little bit ugly.
I'm not an expert with MongoDB but I think in this scenario each of these items should be a separate collection with references to get the results you are after.
Meetings have a Group ID and a list of Person ID attendees.
Groups have a list of Person ID members (people).
If a person can only belong to one group then they can have a single group ID.
Once they go into the database the only option you have with your existing design is checking for name equality which as you say can be done but doesn't seem like the right approach.
Essentially you are using the embedded relationship model with how you are storing 'Person' in 'Group' and 'Meeting' but if you want the same 'Person' object for both then you need to use references for Attendees or both. This seems like the simplest approach to me while not 'fighting' against the standard behaviour.

Categories