Update an Entity with the Collection - c#

I'm having a problem to find a standard, how such an update would look like. I have this model (simplified). Bear in mind that Team is allowed without any player and Team can have up to 500 players:
public class Team
{
public int TeamId { get; set; }
public string Name { get; set; }
public string City { get; set; }
public List<Player> Players { get; set; }
}
public class Player
{
public int PlayerId { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
and this endpoints:
Partial Team Update (without players): [PATCH] /api/teams/{teamId}. Offers me options to update particular fields of the team, but no players.
Update Team (with players): [PUT] /api/teams/{teamId}. In payload data I pass json with entire Team object, including collection of players.
Update Player alone: [PUT] /api/teams/{teamId}/players/{playerId}
I started wondering if I need endpoint #2 at all. The only advantage of endpoint #2 is that I can update many players in one request. I can delete or add many players at once, as well. So I started looking for any standard, how such a popular scenario is being handled in the real world?
I have two options:
Keep endpoint #2 to be able to update/add/remove many child records at the same time.
Remove endpoint #2. Allow to change Team only via PATCH without ability to manipulate Player collection. Player collection can be changed only by endpoints:
[POST] /api/teams/{teamId}/players
[PUT] /api/teams/{teamId}/players/{playerId}
[DELETE] /api/teams/{teamId}/players/{playerId}
Which option is a better practice? Is there a standard how to handle Entity with Collection situation?
Thanks.

This one here https://softwareengineering.stackexchange.com/questions/232130/what-is-the-best-pattern-for-adding-an-existing-item-to-a-collection-in-rest-api could really help you.
In essence it says that POST is the real append verb. If you are not really updating the player resource as a whole, then you are appending just another player to the list.
The main argument with which I agree, is that the PUT verb requires the entire representation of what you are updating.
The patch on the other hand, I would use to update a bunch of resources at the same time.
There is no really wrong or right way to do it. It depends on how you view the domain at the end of the day.
You can have bulk operations and I would certainly use POST with that. There are some things to consider though.
How to handle partial success. Would one fail the others? If not, what is your response?
How will you send back the new resources url? The new resources should be easily discoverable.
Apart from some design considerations, if you are taking about multiple inserts, you'd better do it in bulk. If it's a couple at a time, save yourself and the people who will consume it some time and go with one by one.

Related

What is the best way to write data via MVC into database?

I am working on a homework project using MVC with EF Core.
I am looking for the best way to write data into the database. (I am beginner)
There are two tables. Predbilježba(Enrollment) and Seminari(Seminars)
public class Predbilježba
{
[Key]
public int PredbilježbeID { get; set; }
public string Ime { get; set; }
public string Prezime { get; set; }
public string Adresa { get; set; }
public string Email { get; set; }
public string Telefon { get; set; }
public bool Status { get; set; }
[DataType(DataType.Date)]
public DateTime DatumUpisa { get; set; }
public int SeminarID { get; set; }
public Seminar Seminar { get; set; }
}
public class Seminar
{
public int SeminarID { get; set; }
public string Naziv { get; set; }
public string Opis { get; set; }
[DataType(DataType.Date)]
public DateTime Datum { get; set; }
public bool Popunjen { get; set; }
public ICollection<Predbilježba> Predbilježba { get; set; }
}
I need to insert a sort of Enrollment (Named: Predbilježba) into the database.
Enrollment is connected to a table called Seminars (Named: Seminari).
So when a person is "enrolling" into a "seminar", he/she needs to insert basic data into form (name, phone number, etc.) and they need to choose a "seminar" from a list of given seminars which are in "Seminar" table.
So when they click "Save", their basic data is written into Predbilježba / (eng. Enrollment)" along with chosen "seminar"
So I already have controllers for these 2 models, and appropriate views to create, edit, and so on..
My question is: Do I create a separate controller/model/view to insert data into tables? Can someone give me some example of how it is done?
To clarify further, I need to make user side page where user can "enroll" to "seminar" by writing name, last name, etc.. and by choosing the desired seminar. For now I have functional database, Identity (which will be used later in project), controllers of both models, and appropriate views where I can edit Prebilježbe(eng. Enrollments) and Seminars.
Images of page follow:
So when user clicks Upiši se (eng. enroll) as shown in image number 3. , that selected Seminar, along with basic info that opens after the click (image 4 ) needs to be written into database "Predbilježbe" (eng Enrollments)
This "Upis" page would be a user input page, and "Seminari" and "Predbilježbe" would be admin pages..
If I understand your question correctly, you are asking about good architectural design. Aren't you? (if not please let me know to edit the answer).
You have many architectural choices and possibilities. The easiest one for you to start with is the Service-Repository architectural pattern. I would omit the Repository word here because EF is already (in my opinion) a Repository pattern implementation (at least partially).
So to keep it simple, you would like to start with Service architectural pattern. Which is about creating a class, which injects the DbContext in its construction (let's name it PredbilježbaService). And in this class, you handle all operations of your logic (including database EF queries).
Then you inject this class to your controller and call the required functions from that service class (which deals with the database) in your controller.
The same process can be applied to the other entity Seminar.
P.S. by injecting I mean using any IoC design pattern (in ASP.Net Core, dependency injection is already built-in).
So after these brief words, to answer your question directly, yes, a good software design would be by creating a separate class which handles database operations (adding rows, editing rows, etc.)
It all depends on what your application is supposed to do.
If this is nothing more than a few views around a few tables, then it is perfectly fine to save these objects directly from the controller. The best design is usually the simplest one and there is no need to overcomplicate things with layers, architectural patterns and so on. These are relevant when the size of the project is much larger than in your case.
Good design is all about communication. If someone else is supposed to maintain your project, will it be clear to them where to find the functionality?
I would expect two controllers: one for seminars (called SeminarController) and one for enrollments (called EnrollmentController). These will have methods for viewing, inserting, modifying and deleting data. I would be able to extend your project easily because I know where (and how) to find the code. So your suggestion seems like a good fit.
Response to comment
In the list of seminars has a link pointing to the screen where someone can register for a seminar. That action needs to know which seminar has been selected. The way to do it is to pass the id of the seminar with the request, e.g. /Enrollment/Register/{seminar id}. This results in a GET-request. The form in the enrollment view will POST the inputted data back to the controller.
In the EnrollmentController you would have something like this:
private readonly MyDbContext context;
// Constructor and other methods omitted
[HttpGet]
public ActionResult Register(int seminarId)
{
var seminar = context.Seminars.Single(x => x.Id == seminarId);
return View(seminar);
}
[HttpPost]
public ActionResult Register(Enrollment enrollment)
{
context.Enrollment.Add(enrollment);
return RedirectToAction("index", "Seminar");
}
Depending on the requirements, you might need to insert some validation etc.
You need to study about software architectures a bit to clarify this. Try reading about Layered Architecture for basic structures, and I am assuming you already understand how the MVC architecture works. These will clarify where to perform which task. One of my favorites is the Onion architecture. So basically when you implement an architecture in your code, it becomes much more easy to read, control and track all activities performed within the code.
At the simplest, it is better to split the tasks as below:
1. You define your model classes
2. You create a database class/layer, where you will implement the logic to perform data base queries into your database with respect to the models and return the formatted data (This is where you perform the EF core queries).
3. You create your controllers, where you handle tasks by sending appropriate requests to the database layer and fetch the formatted data.
4. You create your views based on the expected model, and setup the controllers to send the formatted model data to the appropriate view.
A good place to start is here: Tutorial on EF core with MVC
The best way to achieve this in MVC is tu use the nuget package EntityFrameworkCore
Here is a step by step documentation: https://learn.microsoft.com/en-us/ef/core/get-started/
For any further questions, feel free to ask.

Updating DDD Aggregates with Collections

So, I've got an aggregate( Project ) that has a collection of entities (ProjectVariables) in it. The variables do not have Ids on them because they have no identity outside of the Project Aggregate Root.
public class Project
{
public Guid Id { get; set; }
public string Name { get; set; }
public List<ProjectVariable> ProjectVariables { get; set; }
}
public class ProjectVariable
{
public string Key { get; set; }
public string Value { get; set; }
public List<string> Scopes { get; set; }
}
The user interface for the project is an Angular web app. A user visits the details for the project, and can add/remove/edit the project variables. He can change the name. No changes persist to the database until the user clicks save and the web app posts some json to the backend, which in turns passes it down to the domain.
In accordance to DDD, it's proper practice to have small, succinct methods on the Aggregate roots that make atomic changes to them. Examples in this domain could be a method Project.AddProjectVariable(projectVariable).
In order to keep this practice, that means that the front end app needs to track changes and submit them something like this:
public class SaveProjectCommand
{
public string NewName { get; set; }
public List<ProjectVariable> AddedProjectVariables { get; set; }
public List<ProjectVariable> RemovedProjectVariables { get; set; }
public List<ProjectVariable> EditedProjectVariables { get; set; }
}
I suppose it's also possible to post the now edited Project, retrieve the original Project from the repo, and diff them, but that seems a little ridiculous.
This object would get translated into Service Layer methods, which would call methods on the Aggregate root to accomplish the intended behaviors.
So, here's where my questions come...
ProjectVariables have no Id. They are transient objects. If I need to remove them, as passed in from the UI tracking changes, how do identify the ones that need to be removed on the Aggregate? Again, they have no identification. I could add surrogate Ids to the ProjectVariables entity, but that seems wrong and dirty.
Does change tracking in my UI seem like it's making the UI do too much?
Are there alternatives mechanisms? One thought was to just replace all of the ProjectVariables in the Project Aggregate Root every time it's saved. Wouldn't that have me adding a Project.ClearVariables() and the using Project.AddProjectVariable() to the replace them? Project.ReplaceProjectVariables(List) seems to be very "CRUDish"
Am I missing something a key component? It seems to me that DDD atomic methods don't mesh well with a pattern where you can make a number of different changes to an entity before committing it.
In accordance to DDD, it's proper practice to have small, succinct
methods on the Aggregate roots that make atomic changes to them.
I wouldn't phrase it that way. The methods should, as much as possible, reflect cohesive operations that have a domain meaning and correspond with a verb or noun in the ubiquitous language. But the state transitions that happen as a consequence are not necessarily small, they can change vast swaths of Aggregate data.
I agree that it is not always feasible though. Sometimes, you'll just want to change some entities field by field. If it happens too much, maybe it's time to consider changing from a rich domain model approach to a CRUD one.
ProjectVariables have no Id. They are transient objects.
So they are probably Value Objects instead of Entities.
You usually don't modify Value Objects but replace them (especially if they're immutable). Project.ReplaceProjectVariables(List) or some equivalent is probably your best option here. I don't see it as being too CRUDish. Pure CRUD here would mean that you only have a setter on the Variables property and not even allowed to create a method and name it as you want.

How to access data when a viewModel depends on several models

I'm a novice trying to wrap my head around MVVM. I'm trying to build something and have not found an answer on how to deal with this:
I have several models/entities, some of which have logical connections and I am wondering where/when to bring it all together nicely.
Assume we have a PersonModel:
public class PersonModel
{
public int Id { get; set; }
public string Name { get; set; }
...
}
And a ClubModel:
public class ClubModel
{
public int Id { get; set; }
public string Name { get; set; }
...
}
And we have MembershipModel (a Person can have several Club memberships):
public class MembershipModel
{
public int Id { get; set; }
public PersonId { get; set; }
public ClubId { get; set; }
}
All these models are stored somewhere, and the models are persisted "as in" in that data storage.
Assume we have separate repositories in place for each of these models that supplies the standard CRUD operations.
Now I want to create a view model to manage all Persons, e.g. renaming, adding memberships, etc. -> PersonMangementViewModel.
In order to nicely bind a Person with all its properties and memberships, I would also create a PersonView(?)Model that can be used in the PersonManagementViewModel. It could contain e.g. view relevant properties and also the memberships:
public class PersonViewModel : PersonModel
{
public Color BkgnColor { get return SomeLogic(); }
public IEnumerable<MembershipModel> { get; set; }
...
}
My question here is, how would I smartly go about getting the Membership info into the PersionViewModel? I could of course create an instance of the MemberShipRepo directly in the PersionViewModel but that seems not nice, especially if you have a lot of Persons. I could also create all repositories in the PersonManagementViewModel and then pass references into the PersonViewModel.
Or does it make more sense to create another layer (e.g. "service" layer) that returns primarily the PersonViewModel, therefore uses the individual repositories and is called from the PersonManagementViewModel (thus removing the burden from it and allowing for re-use of the service elsewhere)?
Happy to have pointed out conceptional mistakes or some further reading.
Thanks
You are creating separate model for each table I guess. Does not matter, but your models are fragmented. You can consider putting related data together using Aggregate Root and Repository per Aggregate root instead of per model. This concept is discussed under DDD. But as you said you are new to MVVM, there is already lot much to learn. Involving DDD at this stage will only complicate the things.
If you decide to keep the things as is, best and quick thing I can guess is what you are doing now. Get instance of model from data store in View Model (or whatever your location) and map somehow. Tools like Automapper are good but they does not fit each situation. Do not hesitate to map by hand if needed. You can also use mix approach (Automapper + map by hand) to simplify the things.
About service layer, sure... why not. Totally depends on you. If used, this layer typically contain your business logic, mapping, formatting of data, validations etc. Again, each of that thing is up to you.
My suggestions:
Focus on your business objectives first.
Design patterns are good and helpful. Those are extract of many exceptionally capable developers to solve specific problem. Do use them. But, do not unnecessarily stick to it. Read above suggestion. In short, avoid over-engineering. Design patterns are created to solve specific problem. If you do not have that problem, then do not mess-up your code with unnecessary pattern.
Read about Aggregate Root, DDD, Repository etc.
Try your best to avoid Generic Repository.

Store temp data per user Entity Framework 6

I'm creating asp.net-mvc application where user is uploading multiple files.
The data will be compared with db data, processed and exported later. Also paging.
When displaying these data, sorting and filtering is importing.
When data is uploaded, some of them will be stored in db, some will be displayed as not found in db, some will be modified and stored ... etc
My question is, what is the best way to store the uploaded data in order to be available to be process or viewed?
Load in memory
Create temp tables for every session? (even don't know if possible)
Different storage which can be queryable (access data using linq) (JSON??)
Another option.
The source files are (csv or excel)
One of the files example
Name Age Street City Country Code VIP
---------------------------------------------------------
Mike 42 AntwSt Leuven Belgium T5Df No
Peter 32 Ut123 Utricht Netherland T666 Yes
Example of class
public class User
{
public string Name { get; set; }
public Address Address { get; set; } // street, city,country
public Info Info { get; set; } // Age, and Cres
}
public class Info
{
public int Age { get; set; }
public Cres Cres { get; set; }
}
public class Cres
{
public string Code { get; set; }
public bool VIP { get; set; }
}
There are a variety of strategies for handling this (I actually just wrote an entire dissertation over the subject), and there are many different considerations you'll need to take under consideration to achieve this.
Depending on the amount of data present, and what you're doing with it, it may be simple enough to simply store information in Session Storage. Now how you actually implement the session store is up to you, and there are pros and cons to how you decide to do that.
I would personally recommend a server side session store to handle everything and there are a variety of different options for how to do that. For example: SSDB and Redis.
Then from there, you'll need a way of communicating to clients what has actually happened with their data. If multiple clients need to access the same data set and a single user uploads a change, how will you alert every user of this change? Again, there are a lot of options, you can use a Pub/Sub Framework to alert all listening clients. You could also tap into Microsoft's SignalR framework to attempt to handle this.
There's a lot of different If's, But's, Maybe's, etc to the question, and unfortunately I don't believe there is any one perfect solution to you problem without knowing exactly what you're trying to achieve.
If the data size is small and you just need them to exist temporarily, feel free to go with storing them in memory and thus cut all the overhead your would have with other solutions.
You just need to be sure to consider that the data in memory will be gone if the server or the app is switched off for whatever reason.
It might also be a good idea to consider, what happens if the same user performs the operation for the second time, while the operation on the first data is not completed yet. If this can happen to you (it usually does), make sure to use good synchronization mechanisms to prevent race conditions.

ServiceStack.Redis searching cache

I have been using ServiceStack.Redis for a couple of days and the last puzzle in my app is searching cache.
I have a simple object
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public int Age { get; set; }
public string Profession { get; set; }
}
e.g. I want to return all persons which Name is Joe and they are older than 10 years
What is better speed wise?
To run query against database which will return a list of ids and than to get matched records via Redis .GetByIds function.
or
As RedisClient doesn't have native Linq support (doesn't have AsEnumerable only iList) to run GetAll() and than to preform further filtering.
Does anyone have experience with this ?
I've been struggling with same problem, my option was to save a "light " set of data that represents the attributes I need to identify a whole register o attributes I need to filter the whole bunch of data, then go to the database for the rest if necessary.
I just started to use redis and I know this probably is not the best option but its better than go to the database each time even for filtering information.
Hope to know if you found a better solution :)
I think Redis is not a good candidate for such queries, it doesn't have indexes, so you might end up building your own in order to meet speed requirements. Which is not a good idea at all. So I would go with a SQL db which can help me on such queries, or even more complex ones on the Person type.
And then you can use the Redis cache only to store the query results in it so you can easy move through them for things like paging or sorting.
At least this is how we do it in our apps.

Categories

Resources