Implementing CRUD Operations with EF Core in .NET Core

This implementation demonstrates a generic repository patttern for Entity Framework Core operations in a .NET Core application.

Creating the Service Library

Create a class library project named NetCoreDemo.Services to house the data access layer.

Defining the Base Service Interface

public interface IBaseService
{
    T GetById<T>(string id) where T : class;

    IQueryable<T> Filter<T>(Expression<Func<T, bool>> predicate) where T : class;

    T Add<T>(T entity) where T : class;

    IEnumerable<T> AddRange<T>(IEnumerable<T> entities) where T : class;

    void Remove<T>(T entity) where T : class;

    void RemoveRange<T>(IEnumerable<T> entities) where T : class;

    void Modify<T>(T entity) where T : class;

    void Persist();
}

Implementing the Base Service

public class BaseService : IBaseService
{
    protected DbContext Database { get; }

    public BaseService(DbContext context)
    {
        Database = context;
    }

    public T GetById<T>(string id) where T : class
    {
        return Database.Set<T>().Find(id);
    }

    public IQueryable<T> Filter<T>(Expression<Func<T, bool>> predicate) where T : class
    {
        return Database.Set<T>().Where(predicate);
    }

    public T Add<T>(T entity) where T : class
    {
        Database.Set<T>().Add(entity);
        this.Persist();
        return entity;
    }

    public IEnumerable<T> AddRange<T>(IEnumerable<T> entities) where T : class
    {
        Database.Set<T>().AddRange(entities);
        this.Persist();
        return entities;
    }

    public void Remove<T>(T entity) where T : class
    {
        Database.Set<T>().Remove(entity);
        this.Persist();
    }

    public void RemoveRange<T>(IEnumerable<T> entities) where T : class
    {
        foreach (var entity in entities)
        {
            Database.Set<T>().Attach(entity);
        }
        Database.Set<T>().RemoveRange(entities);
        this.Persist();
    }

    public void Modify<T>(T entity) where T : class
    {
        Database.Update(entity);
        this.Persist();
    }

    public void Persist()
    {
        Database.SaveChanges();
    }
}

Creating Domain-Specific Services

Define a user-specific service interface and implementation:

public interface IUserService
{
    UserProfile GetUser(string userId);
    IEnumerable<UserProfile> GetUsersByCondition(Expression<Func<UserProfile, bool>> condition);
    UserProfile CreateUser(UserProfile user);
    void RemoveUser(UserProfile user);
    void UpdateUser(UserProfile user);
}

public class UserService : BaseService, IUserService
{
    public UserService(DbContext context) : base(context) { }
}

Registering Services in Startup

Configrue dependency injection in Startup.cs:

services.AddTransient<DbContext, MyDbContext>();
services.AddTransient<IUserService, UserService>();

Consuming the Service in Controllers

public class UserController : Controller
{
    private readonly IUserService _userService;

    public UserController(IUserService userService)
    {
        _userService = userService;
    }

    public IActionResult GetUser(string id)
    {
        var user = _userService.GetUser(id);
        return View(user);
    }
}

Rendering Data in Views

@model NetCoreDemo.EF.Models.UserProfile

<h1>@Model.Age @Model.Address</h1>

Tags: dotnet efcore CRUD repository-pattern entity-framework

Posted on Fri, 31 Jul 2026 16:30:30 +0000 by bogdan