entityframeworkcore Archives - Learn Smart Coding https://blogs.learnsmartcoding.com/tag/entityframeworkcore/ Everyone can code! Wed, 22 Dec 2021 16:08:04 +0000 en-US hourly 1 https://wordpress.org/?v=6.5.5 209870635 Entity Framework Core commands explained with examples https://blogs.learnsmartcoding.com/2021/12/22/entity-framework-core-commands-explained-with-examples/ https://blogs.learnsmartcoding.com/2021/12/22/entity-framework-core-commands-explained-with-examples/#respond Wed, 22 Dec 2021 16:08:04 +0000 https://karthiktechblog.com/?p=999 Introduction Entity Framework Core commands are useful and make our life a bit easy to execute a few tasks. EF Core is popular Entity Framework data access technology. Entity Framework (EF) Core is a lightweight, extensible and open source. EF Core can serve as an object-relational mapper (O/RM) and it supports many database engines. I […]

The post Entity Framework Core commands explained with examples appeared first on Learn Smart Coding.

]]>
Introduction

Entity Framework Core commands are useful and make our life a bit easy to execute a few tasks. EF Core is popular Entity Framework data access technology. Entity Framework (EF) Core is a lightweight, extensible and open source. EF Core can serve as an object-relational mapper (O/RM) and it supports many database engines.

Entity Framework Core commands explained with examples

I will cover all the options from the three commands.

Commands:

  • database Commands to manage the database.
  • dbcontext Commands to manage DbContext types.
  • migrations Commands to manage migrations.

Short video tutorial

Installation

.NET Core CLI

Use the following .NET Core CLI command from the operating system’s command line to install or update the EF Core SQL Server provider

dotnet add package Microsoft.EntityFrameworkCore.SqlServer

Visual Studio NuGet Package Manager Console

Install-Package Microsoft.EntityFrameworkCore.SqlServer


Get the .NET Core CLI tools

dotnet ef must be installed as a global or local tool.

Also, Install the latest Microsoft.EntityFrameworkCore.Design package

dotnet tool install --global dotnet-ef

dotnet add package Microsoft.EntityFrameworkCore.Design

Refer to how to install Entity Framework Core for more information.

Demo App Explained

For the purpose of the demo, I have a sample restaurant app created using DOTNET CORE. Using the app, we will learn how to use all the dotnet ef commands.

Project structure:

The sample app project has five projects in it. Each serves its purpose and it satisfies the separation of concerns. In the real world, the project has more than one layer hence I choose to demo in a similar structure.

Entity Framework Core commands project structure

Entity Classes

 FoodMenus { get; set; }
    }

    public class FoodImages
    {
        public int Id { get; set; }
        public byte[] Image { get; set; }
        public string Mime { get; set; }
        public string ImageName { get; set; }
        public bool IsActive { get; set; }
        public int? FoodMenusId { get; set; }
        public virtual FoodMenus FoodMenus { get; set; }
    }

    public class FoodMenus
    {
        public int Id { get; set; }
        [Required]
        [MinLength(5), MaxLength(100)]
        public string Name { get; set; }
        [Required]
        [MinLength(100), MaxLength(5000)]
        public string Description { get; set; }
        public decimal Price { get; set; }        
        public bool IsActive { get; set; }
        public short? CategoryId { get; set; }
        public virtual Category Category { get; set; }
        public int? CuisineId { get; set; }
        public virtual Cuisine Cuisine { get; set; }
        public virtual List FoodImages { get; set; }
    }

Now, Let’s get started in exploring each command from dotnet ef command.

Using .NET CORE CLI : Command Prompt

  1. I have opened the database layer project’s location in the command prompt. E.g. “KarthikTechBlog.Restaurant.Data”.

2. To check entity framework core is installed and ready to use, type “dotnet ef” in the command prompt and you will see similar or same details as shown in the image.

dotnet entity framework core

EF Core Commands in Action

migrations : add

dotnet ef migrations add InitialCreate -s ../KarthikTechBlog.Restaurant.API/KarthikTechBlog.Restaurant.API.csproj

To create migrations from the application, we use the command migration add followed by name of the migration. -s “location of the startup project” is to specify the startup project. This is required for the project to build and generate the migration.

dotnet ef migrations add

To generate SQL script for the Entity models, use the below command. Remember the script can be generated only when migrations are created.

migrations : script

dotnet ef migrations script  -s ../KarthikTechBlog.Restaurant.API/KarthikTechBlog.Restaurant.API.csproj
dotnet ef migrations script

migrations: list

This lists all the migrations present in the project.

dotnet ef migrations list  -s ../KarthikTechBlog.Restaurant.API/KarthikTechBlog.Restaurant.API.csproj

migrations: remove

Rollbacks the latest migration.

dotnet ef migrations remove-s ../KarthikTechBlog.Restaurant.API/KarthikTechBlog.Restaurant.API.csproj

database: bundle

Creates an executable to update the database.

dotnet ef migrations bundle -s ../KarthikTechBlog.Restaurant.API/KarthikTechBlog.Restaurant.API.csproj

database : update

This command updates the database with the details present in the migration. If the database is not present, it will create one for us.

dotnet ef database update -s ../KarthikTechBlog.Restaurant.API/KarthikTechBlog.Restaurant.API.csproj

database: drop

Deletes the database. some of the options are

  1. --force or -f which is used to just delete without confirmation.
  2. --dry-run option show which database would be dropped, but don’t drop it.
dotnet ef database drop

dbcontext: scaffold

Generates code for a DbContext and entity types for a database. In order for this command to generate an entity type, the database table must have a primary key.

To scaffold all schemas and tables and puts the new files in the Models folder.

dotnet ef dbcontext scaffold "Server=(localdb)\mssqllocaldb;Database=Shopping;Trusted_Connection=True;" Microsoft.EntityFrameworkCore.SqlServer -o Models


For more options, visit MSDN

dbcontext: optimize

Generates a compiled version of the model used by the DbContext. Added in EF Core 6.

dotnet ef dbcontext optimize

dbcontext: script

Generates a SQL script from the DbContext. Bypasses any migrations.

dotnet ef dbcontext script

Summary

This post covers Entity Framework Core commands and their usage with examples. I hope you enjoyed and learned something new today.

The post Entity Framework Core commands explained with examples appeared first on Learn Smart Coding.

]]>
https://blogs.learnsmartcoding.com/2021/12/22/entity-framework-core-commands-explained-with-examples/feed/ 0 999
Implement create, read, update, and delete functionalities using Entity Framework Core https://blogs.learnsmartcoding.com/2020/01/10/implement-curd-functionalities-in-aspnetcore-using-entity-framework-core/ https://blogs.learnsmartcoding.com/2020/01/10/implement-curd-functionalities-in-aspnetcore-using-entity-framework-core/#comments Fri, 10 Jan 2020 11:02:02 +0000 https://karthiktechblog.com/?p=310 Introduction In this post, I show how to Implement CURD functionality in ASPNETCORE using Entity Framework Core. I have my existing project with bare minimum configuration setup to start and to start with this post demo, I will be using it. To follow along with me for this post, you need to know some basic […]

The post Implement create, read, update, and delete functionalities using Entity Framework Core appeared first on Learn Smart Coding.

]]>
Introduction

In this post, I show how to Implement CURD functionality in ASPNETCORE using Entity Framework Core. I have my existing project with bare minimum configuration setup to start and to start with this post demo, I will be using it.

To follow along with me for this post, you need to know some basic knowledge on setting up a SQL Database to use as our back end.

To know more, take a look at my post CONFIGURE AZURE SQL RELATIONAL DATABASE USING VS 2019

The full demo application is available for free and you may download from my GitHub repository. Take “feature/ImplementCURDFunctionality” branch for this demo.

Getting Started

Now with the demo application in place, we have setup our back end database which has shopping related entities. I will show you how to implement create, read, update, and delete functionalities using Entity Framework Core.

I will be implementing CURD functionalities for Product entity.

To speed up the development work and also to encapsulate the logic required to access data sources, I will be using Repository pattern in this demo and to my demo project.

What is Repository pattern ?

Repositories are classes or components that encapsulate the logic required to access data sources. The functionality written in the repository is centralized and providing better maintainability and decoupling the infrastructure or technology used to access databases from the domain model layer.

As we are using Object-Relational Mapper (ORM) like Entity Framework Core in our project, the code that must be implemented is simplified and it is easy to use.

If you ever think why not to use UnitOfWork pattern along with the repository patter, the answer is NO in my opinion.

This is because, the ORM, in our case Entity Framework Core itself is designed using UnitOfWork design patter as it is tracking all the changes that we make and commits all at once.

It is good idea not to bring in a wrapper for EntityFramework Core.

Repository Setup

Let’s have a generic repository which will have most of the common logic that is required to perform CURD operation on a given entity.

 public interface IGenericRepository
    {
        Task> GetAsync(
            Expression> filter = null,
            Func, IOrderedQueryable> orderBy = null,
            string includeProperties = "", CancellationToken cancellationToken = default, bool trackable = true);

        Task GetByIdAsync(object id, CancellationToken cancellationToken = default);

        Task InsertAsync(TEntity entity, CancellationToken cancellationToken = default);
        void Delete(object id);
        void Delete(TEntity entityToDelete);
        void Update(TEntity entityToUpdate);
        void UpdateStateAlone(TEntity entityToUpdate);
        void DetachEntities(TEntity entityToDetach);
        void DetachEntities(List entitiesToDetach);
    }
 public class GenericRepository : IGenericRepository
   where TEntity : class, new()
    {
        private readonly ManageTextDbContext context;
        internal DbSet dbSet;

        public GenericRepository(ManageTextDbContext context)
        {
            this.context = context;
            dbSet = context.Set();
        }

        public virtual Task> GetAsync(
            Expression> filter = null,
            Func, IOrderedQueryable> orderBy = null,
            string includeProperties = "", CancellationToken cancellationToken = default, bool trackable = true)
        {
            IQueryable query = dbSet;

            if (filter != null)
            {
                query = trackable ? query.Where(filter).AsNoTracking() : query.Where(filter).AsNoTracking();
            }

            foreach (var includeProperty in includeProperties.Split
                (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
            {
                query = query.Include(includeProperty).AsNoTracking();
            }

            if (orderBy != null)
            {
                return orderBy(query).AsNoTracking().ToListAsync();
            }
            else
            {
                return query.AsNoTracking().ToListAsync();
            }
        }

        public virtual Task GetByIdAsync(object id, CancellationToken cancellationToken = default)
        {
            return dbSet.FindAsync(id);
        }

        public virtual Task InsertAsync(TEntity entity, CancellationToken cancellationToken = default)
        {
            return dbSet.AddAsync(entity, cancellationToken);
        }

        public virtual void Delete(object id)
        {
            TEntity entityToDelete = dbSet.Find(id);
            Delete(entityToDelete);
        }

        public virtual void Delete(TEntity entityToDelete)
        {
            if (context.Entry(entityToDelete).State == EntityState.Detached)
            {
                dbSet.Attach(entityToDelete);
            }
            dbSet.Remove(entityToDelete);
        }

        public virtual void Update(TEntity entityToUpdate)
        {
            dbSet.Attach(entityToUpdate);
            context.Entry(entityToUpdate).State = EntityState.Modified;
        }

        public virtual void UpdateStateAlone(TEntity entityToUpdate)
        {            
            context.Entry(entityToUpdate).State = EntityState.Modified;
        }

        public void DetachEntities(TEntity entityToDetach)
        {
            context.Entry(entityToDetach).State = EntityState.Detached;            
        }

        public void DetachEntities(List entitiesToDetach)
        {
            foreach (var entity in entitiesToDetach)
            {
                context.Entry(entity).State = EntityState.Detached;
            }
        }

    }

Setup repository for Entities

In this demo, I need a repository for Product entity, below is the code to setup IProductRepository.

using KarthikTechBlog.Shopping.Core;
using System.Threading.Tasks;

namespace KarthikTechBlog.Shopping.Data
{
    public interface IProductRepository : IGenericRepository
    {
        Task CommitAsync();
    }
}
using KarthikTechBlog.Shopping.Core;
using System.Threading.Tasks;

namespace KarthikTechBlog.Shopping.Data
{
    public class ProductRepository : GenericRepository, IProductRepository
    {
        private readonly ShoppingDbContext _context;
        public ProductRepository(ShoppingDbContext context) : base(context)
        {
            _context = context;
        }

        public Task CommitAsync()
        {
            return _context.SaveChangesAsync();
        }
    }
}

Create Product Service

Let’s create a service for the Product entity and this will access all product related functionality.

using KarthikTechBlog.Shopping.Core;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace KarthikTechBlog.Shopping.Service
{
    public interface IProductService
    {
        Task CreateProductAsync(Product product);
        Task UpdateProductAsync(Product product);
        Task DeleteProductAsync(int productId);
        Task> GetProductsAsync();
        Task GetProductAsync(int productId);
    }
}

using KarthikTechBlog.Shopping.Core;
using KarthikTechBlog.Shopping.Data;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace KarthikTechBlog.Shopping.Service
{
    public class ProductService: IProductService
    {
        public ProductService(IProductRepository productRepository)
        {
            ProductRepository = productRepository;
        }

        public IProductRepository ProductRepository { get; }

        public async Task CreateProductAsync(Product product)
        {
            await ProductRepository.InsertAsync(product);
            return await ProductRepository.CommitAsync();
        }

        public async Task DeleteProductAsync(int productId)
        {
            ProductRepository.Delete(productId);
            return await ProductRepository.CommitAsync();
        }

        public Task GetProductAsync(int productId)
        {
            return ProductRepository.GetByIdAsync(productId);
        }

        public Task> GetProductsAsync()
        {
            return ProductRepository.GetAsync();
        }

        public async Task UpdateProductAsync(Product product)
        {
            ProductRepository.Update(product);
            return await ProductRepository.CommitAsync();
        }
    }
}

Now all we left here is controller, come let’s write some minimum code to complete our CURD functionality for Product entity.

Read Product data (GET API)

    public class ProductController : ControllerBase
    {
        public ProductController(IProductService productService)
        {
            ProductService = productService;
        }

        public IProductService ProductService { get; }

        public async Task GetProduct(
           [FromQuery] int productId)
        {
            var product = await ProductService.GetProductAsync(productId);
            return Ok(product);
        }
    }

The controller code is pretty simply, that is the beauty of using right layers to talk to back end database. In this case, we inject the Service layer for Product and call the required methods to get Product data.

Now, one thing in this I would like to change. Currently we are returning the entity model itself from the controller. what if we need to add custom data annotation or custom model validation? I will show you the custom validation in another post.

For now, let’s create view model for that we need to send to client which is our API consuming client.

I have created ProductViewModel as the model for any GET API calls.

public class ProductViewModel
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public decimal Price { get; set; }
        public DateTime? AvailableSince { get; set; }
        public int StockCount { get; set; }
        public int CategoryId { get; set; }
    }

Configure AutoMapper

Now, we need to map our Entity properties to custom view model. There are two ways we can do this, one is to manually assign values and other best one is to use AutoMapper.

Add auto mapper package to the API project to setup AutoMapper

AutoMapper Version="8.0.0" AutoMapper.Extensions.Microsoft.DependencyInjection Version="6.0.0"

Configure AutoMapper for the Entities

Add a class AutoMapperConfiguration to the API project and inherit Profile class from AutoMapper. Create configuration for Product and ProductViewModel.

 public class AutoMapperConfiguration : Profile
    {
        public AutoMapperConfiguration()
        {
            CreateMap(); //source, destination
        }
    }

Modified Controller Code

using AutoMapper;
using KarthikTechBlog.Shopping.API.ViewModel;
using KarthikTechBlog.Shopping.Service;
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;

namespace KarthikTechBlog.Shopping.API.Controllers
{
    public class ProductController : ControllerBase
    {
        public ProductController(IProductService productService, IMapper mapper)
        {
            ProductService = productService;
            Mapper = mapper;
        }

        public IProductService ProductService { get; }
        public IMapper Mapper { get; }

        public async Task GetProduct(
           [FromQuery] int productId)
        {
            var product = await ProductService.GetProductAsync(productId);
            var model = Mapper.Map(product);
            return new OkObjectResult(model);
        }
    }
}

Complete Controller Code to Implement CURD functionality in ASPNETCORE

using AutoMapper;
using KarthikTechBlog.Shopping.API.ViewModel;
using KarthikTechBlog.Shopping.Service;
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using KarthikTechBlog.Shopping.Core;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using System.Collections.Generic;

namespace KarthikTechBlog.Shopping.API.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class ProductController : ControllerBase
    {
        public ProductController(IProductService productService, IMapper mapper)
        {
            ProductService = productService;
            Mapper = mapper;
        }

        public IProductService ProductService { get; }
        public IMapper Mapper { get; }

        [HttpGet("{productId}")]
        [ProducesResponseType(typeof(ProductViewModel), StatusCodes.Status200OK)]
        [ProducesResponseType(typeof(ModelStateDictionary), StatusCodes.Status404NotFound)]
        public async Task GetProduct(
           [FromRoute] int productId)
        {
            var product = await ProductService.GetProductAsync(productId);

            if (product == null)
                return NotFound();

            var model = Mapper.Map(product);
            return new OkObjectResult(model);
        }

        [HttpGet("")]
        [ProducesResponseType(typeof(IReadOnlyList), StatusCodes.Status200OK)]
        [ProducesResponseType(typeof(ModelStateDictionary), StatusCodes.Status404NotFound)]
        public async Task GetProducts()
        {
            var products = await ProductService.GetProductsAsync();

            var model = Mapper.Map>(products);
            return new OkObjectResult(model);
        }

        [HttpPost("", Name = "CreateProduct")]
        [ProducesResponseType(StatusCodes.Status200OK)]
        [ProducesResponseType(typeof(ModelStateDictionary), StatusCodes.Status400BadRequest)]
        public async Task CreateProduct(
           [FromBody] CreateProduct product)
        {
            var entityToAdd = Mapper.Map(product);

            await ProductService.CreateProductAsync(entityToAdd);

            return Ok();
        }

        [HttpPut("{productId}", Name = "UpdateProduct")]
        [ProducesResponseType(StatusCodes.Status200OK)]
        [ProducesResponseType(typeof(ModelStateDictionary), StatusCodes.Status400BadRequest)]
        [ProducesResponseType(StatusCodes.Status404NotFound)]
        public async Task UpdateProduct(
           [FromRoute] int productId, [FromBody] UpdateProduct product)
        {

            var existingProduct = await ProductService.GetProductAsync(productId);

            if (existingProduct == null)
                return NotFound();

            var entityToUpdate = Mapper.Map(product);

            await ProductService.UpdateProductAsync(entityToUpdate);

            return Ok();
        }


        [HttpDelete("{productId}", Name = "DeleteProduct")]
        [ProducesResponseType(StatusCodes.Status200OK)]
        [ProducesResponseType(typeof(ModelStateDictionary), StatusCodes.Status400BadRequest)]
        [ProducesResponseType(StatusCodes.Status404NotFound)]
        public async Task DeleteProduct(
          [FromRoute] int productId)
        {

            var existingProduct = await ProductService.GetProductAsync(productId);

            if (existingProduct == null)
                return NotFound();

            await ProductService.DeleteProductAsync(productId);

            return Ok();
        }

    }
}

One last thing to include is to configure the DI in the ConfigureServices method of startup class.

 public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext(options =>
               options.UseSqlServer(Configuration.GetConnectionString("DbContext")));
                        
            services.AddScoped();
            services.AddScoped();
            services.AddAutoMapper();

            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
        }

Additional Resource

Design the infrastructure persistence layer

Conclusion

In this post, I showed how to implement create, read, update, and delete functionalities using Entity Framework Core. This post is part of learning track for azure AZ-203 certification. I have covered end to end coding that is required to write a good Restful API. In next post, I will show how to create API documentation using OpenAPI & Swagger.

That’s all from this post. If you have any questions or just want to chat with me, feel free to leave a comment below.

The post Implement create, read, update, and delete functionalities using Entity Framework Core appeared first on Learn Smart Coding.

]]>
https://blogs.learnsmartcoding.com/2020/01/10/implement-curd-functionalities-in-aspnetcore-using-entity-framework-core/feed/ 1 310