DEV Community

Cover image for All CRUD Operations with Entity Framework Core (GET, POST, PUT & DELETE)
Patrick God
Patrick God

Posted on • Edited on

All CRUD Operations with Entity Framework Core (GET, POST, PUT & DELETE)

This tutorial series is now also available as an online video course. You can watch the first hour on YouTube or get the complete course on Udemy. Or you just keep on reading. Enjoy! :)

Entity Framework Core (continued)

GET Implementations

The very first thing we have to do to be able to access our RPG characters is to get access to the DataContext. We make use of dependency injection for that and add the context to the constructor of our CharacterService. Again, we can initialize this field from the parameter and change the name a little bit.



private readonly DataContext _context;
public CharacterService(IMapper mapper, DataContext context)
{
    _context = context;
    _mapper = mapper;
}


Enter fullscreen mode Exit fullscreen mode

With that, the _context is available everywhere in our CharacterService.

In the GetAllCharacters() method we add a new line to get the characters from the database.



List<Character> dbCharacters = await _context.Characters.ToListAsync();


Enter fullscreen mode Exit fullscreen mode

Then, instead of selecting the static characters list, we use our new dbCharacters.



public async Task<ServiceResponse<List<GetCharacterDto>>> GetAllCharacters()
{
    ServiceResponse<List<GetCharacterDto>> serviceResponse = new ServiceResponse<List<GetCharacterDto>>();
    List<Character> dbCharacters = await _context.Characters.ToListAsync();
    serviceResponse.Data = dbCharacters.Select(c => _mapper.Map<GetCharacterDto>(c)).ToList();
    return serviceResponse;
}


Enter fullscreen mode Exit fullscreen mode

These are all the necessary changes. When we test that in Postman - URL is http://localhost:5000/Character/GetAll - we get no characters back, of course, because we haven’t added any characters in the database yet. So let’s add one in the SQL Server Management Studio.

We don’t have to enter an Id, just the name, hitpoints, and so on, and confirm the new entry with enter.

First character in SQL Server Management Studio

Let’s run another test and there is our Frodo.



{
    "data": [
        {
            "id": 1,
            "name": "Frodo",
            "hitPoints": 100,
            "strength": 10,
            "defense": 10,
            "intelligence": 10,
            "class": 1
        }
    ],
    "success": true,
    "message": null
}


Enter fullscreen mode Exit fullscreen mode

Receiving a single RPG character is quite similar.

Let’s get the database character first. We do that with Character dbCharacter = await _context.Characters.FirstOrDefaultAsync(c => c.Id == id);.

Then we simply map that dbCharacter.



public async Task<ServiceResponse<GetCharacterDto>> GetCharacterById(int id)
{
    ServiceResponse<GetCharacterDto> serviceResponse = new ServiceResponse<GetCharacterDto>();
    Character dbCharacter = await _context.Characters.FirstOrDefaultAsync(c => c.Id == id);
    serviceResponse.Data = _mapper.Map<GetCharacterDto>(dbCharacter);
    return serviceResponse;
}


Enter fullscreen mode Exit fullscreen mode

By the way, you see that the yellow lines have disappeared because we’re finally using asynchronous methods. That’s cool, isn’t it?

Anyways, to test the new GetCharacterById() method, let’s add a second character to the database manually.

I’d like to call this guy Sam again.

Second character in SQL Server Management Studio

Again, entering an Id is not necessary, SQL Server is doing this for us.

Alright. Back to Postman with the URL http://localhost:5000/Character/2 and we’re getting Sam back.



{
    "data": {
        "id": 2,
        "name": "Sam",
        "hitPoints": 100,
        "strength": 10,
        "defense": 10,
        "intelligence": 10,
        "class": 1
    },
    "success": true,
    "message": null
}


Enter fullscreen mode Exit fullscreen mode

Let’s get all RPG characters again.



{
    "data": [
        {
            "id": 1,
            "name": "Frodo",
            "hitPoints": 100,
            "strength": 10,
            "defense": 10,
            "intelligence": 10,
            "class": 1
        },
        {
            "id": 2,
            "name": "Sam",
            "hitPoints": 100,
            "strength": 10,
            "defense": 10,
            "intelligence": 10,
            "class": 1
        }
    ],
    "success": true,
    "message": null
}


Enter fullscreen mode Exit fullscreen mode

There are our mighty knights.

POST Implementations

When we want to add an RPG character to the database, the first thing that stands out is that we don’t need to increase the Id manually. SQL Server will do this for us.

Apart from that, we won’t add the character to the static characters list anymore.

Instead, we use the AddAsync() method to add the RPG character to the database.



await _context.Characters.AddAsync(character);


Enter fullscreen mode Exit fullscreen mode

The next step is very important.

Since we made a change to the database, we have to save these changes explicitly. We do that with await _context.SaveChangesAsync().

Last but not least, we return all RPG characters from the database.



public async Task<ServiceResponse<List<GetCharacterDto>>> AddCharacter(AddCharacterDto newCharacter)
{
    ServiceResponse<List<GetCharacterDto>> serviceResponse = new ServiceResponse<List<GetCharacterDto>>();
    Character character = _mapper.Map<Character>(newCharacter);

    await _context.Characters.AddAsync(character);
    await _context.SaveChangesAsync();
    serviceResponse.Data = (_context.Characters.Select(c => _mapper.Map<GetCharacterDto>(c))).ToList();
    return serviceResponse;
}


Enter fullscreen mode Exit fullscreen mode

That’s it!

Let’s test that in Postman. The URL is http://localhost:5000/Character/, the HTTP method is POST, and we send a JSON in the body with just the name, hitpoints and another class for starters.



{
    "name" : "Percival",
    "hitpoints" : 200,
    "class": 2
}


Enter fullscreen mode Exit fullscreen mode

Again, we don’t have to send an Id and we don’t have to set it manually in the service. When we run this, we get all RPG characters back, and we can see the new entry in the database.

Add RPG character in database

PUT Implementations

To update an RPG character, we first have to find a particular character in the database.

Instead of searching for the character with the given Id in the static characters list, we access the characters of the data context and search the RPG characters asynchronously.



Character character = await _context.Characters.FirstOrDefaultAsync(c => c.Id == updatedCharacter.Id);


Enter fullscreen mode Exit fullscreen mode

Overriding the properties stays the same.

But after that, we have to access the data context again and call the Update() method on that particular character.

Since we made a change to the character table, we have to save these changes again with await _context.SaveChangesAsync();.



_context.Characters.Update(character);
await _context.SaveChangesAsync();


Enter fullscreen mode Exit fullscreen mode

That’s it already!

Receiving the particular RPG character from the database, change the values, update the character in the database and save the changes again.

Again, it’s time to test that in Postman.

Let's receive a single character first. With the help of the result, we already have the proper JSON object to use for the update call. Let’s get Frodo with Id 1, for instance.



{
    "id": 1,
    "name": "Frodo",
    "hitPoints": 100,
    "strength": 10,
    "defense": 10,
    "intelligence": 10,
    "class": 1
}


Enter fullscreen mode Exit fullscreen mode

Now, we can update Frodo’s properties with the URL http://localhost:5000/Character/, the HTTP method PUT and this JSON object here.



{
    "id": 1,
    "name": "Frodo",
    "hitPoints": 200,
    "strength": 20,
    "defense": 10,
    "intelligence": 10,
    "class": 2
}


Enter fullscreen mode Exit fullscreen mode

You can change anything you want except the Id, of course, because that’s how we find the correct RPG character.

When we run this call, we get the correct result and we can also see the changes in the SQL Server Management Studio.

Update in SQL Server Management Studio

Remember, all properties of the characters will be changed in our update method. So make sure to get the correct values of the character first or implement methods to update single properties. Otherwise, you would overwrite the properties of a character with default values.

Just keep that in mind.

DELETE Implementations

Alright, only deleting a character is left and then you know how to implement all the CRUD operations with Entity Framework Core.

First, let’s remove the static characters list because we won’t need it anymore.

Of course, this results in some errors in our DeleteCharacter() method, because this is the only method left using the characters list.

But don’t worry, we’ll fix that right now. Maybe you already know how to fix this.

In essence, we have to replace the old characters list with _context.Characters.



Character character = _context.Characters.First(c => c.Id == id);
_context.Characters.Remove(character);

serviceResponse.Data = (_context.Characters.Select(c => _mapper.Map<GetCharacterDto>(c))).ToList();


Enter fullscreen mode Exit fullscreen mode

After that, we call the asynchronous FirstAsync() method instead of First(). Don’t forget to add the await keyword.



Character character = await _context.Characters.FirstAsync(c => c.Id == id);


Enter fullscreen mode Exit fullscreen mode

Now, only one thing is missing. We have to save the changes to the database. So let’s call await _context.SaveChangesAsync(); and we’re done.



Character character = await _context.Characters.FirstAsync(c => c.Id == id);
_context.Characters.Remove(character);
await _context.SaveChangesAsync();

serviceResponse.Data = (_context.Characters.Select(c => _mapper.Map<GetCharacterDto>(c))).ToList();


Enter fullscreen mode Exit fullscreen mode

To test this in Postman, we can remove the RPG character with Id 3, for instance. The URL is http://localhost:5000/Character/3 and the HTTP method is DELETE. Hit ‘Send’, and the character is gone. You can also see that in the database table, of course.

Summary

Great! You successfully implemented all CRUD operations, meaning create, read, update and delete, with Entity Framework Core.

All your changes are now stored persistently in the database.

You now know what object-relational mapping is, how code-first migration works and how to use it with a SQL Server database. Additionally, you looked at your database with SQL Server Management Studio.

Regarding the code, you learned what the DbContext is and how to provide a connection string to access the database with all its entities.

Alright, it’s time to add the first relation to the RPG characters.

In the next section, we will add users who can own several characters. But before they can do that, they have to register for an account. So, in the next section, we will add a relation and also implement authentication.


That's it for the 6th part of this tutorial series. I hope it was useful for you. To get notified for the next part, simply follow me here on dev.to or subscribe to my newsletter. You'll be the first to know.

See you next time!

Take care.


Next up: Basic Authentication with a .NET Core Web API

Image created by cornecoba on freepik.com.


But wait, there’s more!

Top comments (2)

Collapse
 
samselfridge profile image
samselfridge • Edited

Curious why theres Update(), Remove(), Add(), but also AddAsync().

Going by this SO answer, its in the lang for special cases and we should probably be using the sync Add() version in this example - plus it keeps things consistent over the CRUD operations.

stackoverflow.com/a/42042173/901311

Collapse
 
aaiing profile image
AAI INGENIERIA • Edited

how to querying with async method two parameters?, sample:

trying this

return await _dataContext.Usuario.SingleOrDefaultAsync(x => x.Rut == rut && x.Verificador == verificador);

return null :(

querying with one parameter, work fine