<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Aravindha Samy B</title>
    <description>The latest articles on DEV Community by Aravindha Samy B (@aravindhasamy).</description>
    <link>https://dev.to/aravindhasamy</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2649391%2F17b94c5b-b42d-46bc-adf8-316107c6a43a.jpeg</url>
      <title>DEV Community: Aravindha Samy B</title>
      <link>https://dev.to/aravindhasamy</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aravindhasamy"/>
    <language>en</language>
    <item>
      <title>Simplifying CRUD Operations Using Primary Constructors for Dependency Injection with Generic Interfaces</title>
      <dc:creator>Aravindha Samy B</dc:creator>
      <pubDate>Sat, 04 Jan 2025 17:01:35 +0000</pubDate>
      <link>https://dev.to/aravindhasamy/simplifying-crud-operations-using-primary-constructors-for-dependency-injection-with-generic-1hm8</link>
      <guid>https://dev.to/aravindhasamy/simplifying-crud-operations-using-primary-constructors-for-dependency-injection-with-generic-1hm8</guid>
      <description>&lt;p&gt;In .NET  development, leveraging primary constructors for dependency injection (DI) alongside generic interfaces offers a streamlined approach to managing CRUD (Create, Read, Update, Delete) operations. This combination enhances code clarity, reduces boilerplate, and promotes scalable architecture in API development.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Managing dependencies efficiently is crucial for building maintainable APIs in .NET . This article explores how to simplify CRUD operations by integrating primary constructors for DI and utilizing generic interfaces. By adopting these practices, developers can enhance code reusability, maintainability, and scalability in their .NET applications.&lt;/p&gt;

&lt;p&gt;By using the Generic Interface  We can use it for all controllers and make the crud very simple and very scalable . In other hand we can pass the instance in class level instead of creating a constructor. This is the another advance in . Net .&lt;/p&gt;

&lt;h2&gt;
  
  
  Base Controller
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;BaseController&lt;/code&gt; inherits from &lt;code&gt;ControllerBase&lt;/code&gt;, providing a base class for other controllers to inherit common attributes and behaviors related to API controllers.&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    [ApiController]&lt;br&gt;
    [Route("api/[controller]")]
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class BaseController : ControllerBase
{

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Using Primary Constructors for Dependency Injection&lt;br&gt;
&lt;/h2&gt;

&lt;p&gt;Primary constructors allow for direct dependency injection into controllers without explicit constructor definitions. This approach simplifies code structure and improves readability. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Now we can Create the Other Controllers. For sample I am here creating the &lt;code&gt;UserController. Here’s how you can implement primary constructors in a&lt;/code&gt;User Controller`&lt;/p&gt;
&lt;h2&gt;
  
  
  User Controller
&lt;/h2&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;UserController&lt;/code&gt; inherits from &lt;code&gt;BaseController&lt;/code&gt;. This inheritance allows &lt;code&gt;UserController&lt;/code&gt; to inherit the &lt;code&gt;[ApiController]&lt;/code&gt; and &lt;code&gt;[Route("api/[controller]")]&lt;/code&gt; attributes, making these attributes available to all methods within &lt;code&gt;UserController&lt;/code&gt;. &lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class UserController(IUserRepo _userRepo) : BaseController&lt;br&gt;
{&lt;br&gt;
    //URL : api/User&lt;br&gt;
    [HttpPost]&lt;br&gt;
    public async Task&amp;lt;IActionResult&amp;gt;  Create(User user)&lt;br&gt;
    {&lt;br&gt;
        try&lt;br&gt;
        {&lt;br&gt;
            var res = await _userRepo.CreateAsync(user);&lt;br&gt;
            return Ok(res);&lt;br&gt;
        }&lt;br&gt;
        catch (Exception ex)&lt;br&gt;
        {&lt;br&gt;
            return BadRequest(ex.Message);&lt;br&gt;
        }&lt;br&gt;
    }
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//URL : api/User
[HttpGet]
public async Task&amp;amp;lt;ActionResult&amp;amp;lt;IEnumerable&amp;amp;lt;User&amp;amp;gt;&amp;amp;gt;&amp;amp;gt; GetAll()
{
    IEnumerable&amp;amp;lt;User&amp;amp;gt; user= await _userRepo.GetByAllAsync();
    return Ok(user);
}

// URL : api/User/5
[HttpGet("{id}")]
public async Task&amp;amp;lt;IActionResult&amp;amp;gt; Get(long id)
{
    try
    {
        var user = await _userRepo.GetAsync(id);
        if (user == null)
        {
            return NotFound();
        }
        return Ok(user);
    }
    catch (Exception ex)
    {
        return BadRequest(ex.Message);
    }
}

// URL : api/User/5
[HttpPut("{id}")]
public async Task&amp;amp;lt;IActionResult&amp;amp;gt; Update(long id,User user)
{
    try
    {
        if(id!=user.Id)
        {
            return BadRequest("Id Mismatch");
        }
        var res = await _userRepo.UpdateAsync(user);
        return Ok(res);
    }
    catch (Exception ex)
    {
        return BadRequest(ex.Message);
    }
}

// URL : api/User/5
[HttpDelete("{id}")]
public async Task&amp;amp;lt;IActionResult&amp;amp;gt; Delete(long id)
{
    try
    {
        await _userRepo.DeleteAsync(id);  
        return NoContent();
    }
    catch (Exception ex)
    {
        return BadRequest(ex.Message);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;}&lt;br&gt;
&lt;/p&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  UserRepo&lt;br&gt;
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;UserRepo&lt;/code&gt; class implements both &lt;code&gt;IUserRepo&lt;/code&gt; for user-specific operations and &lt;code&gt;IGenericRepo&amp;lt;User&amp;gt;&lt;/code&gt; for generic CRUD operations.&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    public class UserRepo(DbContext _context):GenericRepo&amp;lt;User&amp;gt;(_context),IUserRepo&lt;br&gt;
    {
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  IUserRepo&lt;br&gt;
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;IUserRepo&lt;/code&gt; interface defines specific operations that are tailored for the &lt;code&gt;User&lt;/code&gt; entity.&lt;br&gt;
If you have any specific request you write here and implement in the User Repo.&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public interface IUserRepo:IGenericRepo&amp;lt;User&amp;gt;&lt;br&gt;
{&lt;br&gt;
}&lt;br&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  IGeneric&lt;br&gt;
&lt;/h2&gt;

&lt;p&gt;Now I am going to create an Interface generically . These are all the operations common to all the  entities&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public interface IGenericRepo&amp;lt;T&amp;gt; where T:class&lt;br&gt;
{&lt;br&gt;
     Task&amp;lt;T&amp;gt; CreateAsync(T entity);&lt;br&gt;
     Task&amp;lt;T&amp;gt; GetAsync(long id);&lt;br&gt;
     Task&amp;lt;T&amp;gt; UpdateAsync(T entity);&lt;br&gt;
     Task DeleteAsync(long id);&lt;br&gt;
     Task&amp;lt;IEnumerable&amp;lt;T&amp;gt;&amp;gt; GetByAllAsync();&lt;br&gt;
 }&lt;br&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Generic&lt;br&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;GenericRepo&amp;lt;T&amp;gt;&lt;/code&gt; implements the &lt;code&gt;IGenericRepo&amp;lt;T&amp;gt;&lt;/code&gt; interface, which defines the generic repository operations (&lt;code&gt;CreateAsync&lt;/code&gt;, &lt;code&gt;GetAsync&lt;/code&gt;, &lt;code&gt;UpdateAsync&lt;/code&gt;, &lt;code&gt;DeleteAsync&lt;/code&gt;, &lt;code&gt;GetByAllAsync&lt;/code&gt;). This approach allows for generic handling of CRUD operations across different entity types.&lt;/p&gt;

&lt;p&gt;Now we can Implement this interface dynamically for all the entities&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class GenericRepo&amp;lt;T&amp;gt;(DbContext _context) : IGenericRepo&amp;lt;T&amp;gt; where T : class&lt;br&gt;
 {&lt;br&gt;
 internal readonly DbSet&amp;lt;T&amp;gt; _dbSet = _context.Set&amp;lt;T&amp;gt;();

&lt;p&gt;public async Task&amp;lt;T&amp;gt; CreateAsync(T entity)&lt;br&gt;
 {&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; var res= await _dbSet.AddAsync(entity);
 await save();
 return res.Entity;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;}      &lt;/p&gt;

&lt;p&gt;public async Task DeleteAsync(long id)&lt;br&gt;
 {&lt;br&gt;
     var entity = await _dbSet.FindAsync(id);&lt;br&gt;
     Console.WriteLine(entity);&lt;br&gt;
     if (entity != null)&lt;br&gt;
     {&lt;br&gt;
         _dbSet.Remove(entity);&lt;br&gt;
         await save();&lt;br&gt;
     }&lt;br&gt;
 }&lt;/p&gt;

&lt;p&gt;public async Task&amp;lt;T&amp;gt; GetAsync(long id)&lt;br&gt;
 {&lt;br&gt;
     return await _dbSet.FindAsync(id);&lt;br&gt;
 }&lt;/p&gt;

&lt;p&gt;public async Task&amp;lt;IEnumerable&amp;lt;T&amp;gt;&amp;gt; GetByAllAsync()&lt;br&gt;
 {&lt;br&gt;
     return await _dbSet.ToListAsync();&lt;br&gt;&lt;br&gt;
 }&lt;/p&gt;

&lt;p&gt;public async Task&amp;lt;T&amp;gt; UpdateAsync(T entity)&lt;br&gt;
 {&lt;br&gt;
     _context.Entry(entity).State = EntityState.Modified;&lt;br&gt;
     await save();&lt;br&gt;
     return entity;&lt;br&gt;
 }&lt;br&gt;
 private async Task save()&lt;br&gt;
 {&lt;br&gt;
     try&lt;br&gt;
     {&lt;br&gt;
         await _context.SaveChangesAsync();&lt;br&gt;
     }&lt;br&gt;
     catch (DbUpdateException ex)&lt;br&gt;
     {&lt;br&gt;
         throw new ApplicationException("Error saving changes to the database.", ex);&lt;br&gt;
     }&lt;br&gt;
     catch (Exception ex)&lt;br&gt;
     {&lt;br&gt;
         throw new ApplicationException("An error occurred while saving changes.", ex);&lt;br&gt;
     }&lt;br&gt;
 }&lt;br&gt;
 }&lt;br&gt;
&lt;/p&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Conclusion&lt;br&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Recap of the benefits of using generic interfaces and inheritance for scalable and maintainable .NET applications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simplicity&lt;/strong&gt;: Reduces boilerplate by eliminating explicit constructor definitions and repetitive CRUD implementation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability&lt;/strong&gt;: Promotes scalable architecture with generic repositories that can handle operations for any entity type.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maintainability&lt;/strong&gt;: Enhances code maintainability by centralizing data access logic and dependency management.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>csharp</category>
      <category>generic</category>
      <category>dotnet</category>
    </item>
  </channel>
</rss>
