locked
Using generics with Entity Framework RRS feed

  • Question

  • User-1526035670 posted
    Hi

    I'm going through a few tutorials in bringing Entity Framework into my projects.

    I've broken this into 2 class library projects. Data access and business layer.

    Data access: I add the entity Framework data object (edmx) file. My database has 4 tables
    Business Layer: is going to carry out all CRUD operations on these tables.

    The tutorial misses the point of having a clean way to add, edit etc records for multiple tables. At present it has the context and then uses a using statement to add the records or edit under the Business Layer.

    Is there a cleaner approach I could utilise? In previous projects I would generally create an Interface and then have a class implement that but I'm sure entity Framework must have a cleaner approach, possibly using generics to add, edit on multiple tables?

    Let me know if this doesn't make sense or it would be awesome if someone could give me an example of what they do with their project in similar cases.

    Thanks in advance
    Friday, May 29, 2020 9:36 PM

Answers

  • User1120430333 posted

    The business layer's job is not to carryout CRUD operations with the database. The DAL's job is to carryout all CRUD operations with the database. At best, the job of the BLL is to implement business logic, and the BLL may act as a pass-through acting upon an object like a DTO that may be passing through the BLL, but a BLL object calls upon a DAL object like a DAO to carryout CRUD operations with the database.

    https://javarevisited.blogspot.com/2013/01/data-access-object-dao-design-pattern-java-tutorial-example.html

    Note: A DAO is on a per table basis.

    https://www.tutorialspoint.com/design_pattern/data_access_object_pattern.htm

    Also,  you may want to look into the DTO pattern. 

    https://www.codeproject.com/articles/1050468/data-transfer-object-design-pattern-in-csharp

    DTO(s) are kept in a classlib project. I call it Entities, and all layers that need to know about the DTO(s) have project reference to Entities.

    Example of DAL using the DAO and DTO patterns along with EF..

    using Entities;
    using System.Collections.Generic;
    using System.Threading.Tasks;
    
    namespace DAL
    {
        public interface IDaoPayroll
        {
            Task<List<DtoPayroll>> GetAll();
            Task<DtoPayroll> Find(int id);
            Task<DtoPayroll> FindPayRollByAuthorId(int id);
            Task Add(DtoPayroll dto);
            Task Update(DtoPayroll dto);
            Task Delete(int id);
        }
    }
    
    =================================================================
    
    using DAL.Models;
    using System;
    using System.Threading.Tasks;
    using Entities;
    using System.Collections.Generic;
    using Microsoft.EntityFrameworkCore;
    using System.Data.SqlClient;
    using System.Linq;
    
    namespace DAL
    {
        public class DaoPayroll :IDaoPayroll
        {
            private PublishingCompanyContext pc;
            private IDaoAuthor _daoauthor;
    
            public DaoPayroll(PublishingCompanyContext dbcontext, IDaoAuthor daoAuthor)
            {
                pc = dbcontext;
                _daoauthor = daoAuthor;
            }
    
            public async Task<List<DtoPayroll>> GetAll()
            {
                var dtos = new List<DtoPayroll>();
    
                var payrolls = await pc.Payroll.ToListAsync();
    
                foreach (var payroll in payrolls)
                {
                    var dtoauthor = await _daoauthor.Find(payroll.AuthorId); 
    
                    var dto = new DtoPayroll
                    {
                        PayRollId = payroll.PayrollId,
                        AuthorId = payroll.AuthorId,
                        AuthorFirstName = dtoauthor.FirstName,
                        AuthorLastName = dtoauthor.LastName,
                        Salary = payroll.Salary
                    };
    
                    dtos.Add(dto);
                }
    
                return dtos;
            }
    
            public async Task<DtoPayroll> Find(int id)
            {
                var dto = new DtoPayroll();
    
                var payroll = await pc.Payroll.FindAsync(id);
    
                if (payroll != null)
                { 
                    var dtoauthor = await _daoauthor.Find(payroll.AuthorId);
    
                    if (dtoauthor != null)
                    {
                        dto.PayRollId = payroll.PayrollId;
                        dto.AuthorId = payroll.AuthorId;
                        dto.AuthorFirstName = dtoauthor.FirstName;
                        dto.AuthorLastName = dtoauthor.LastName;
                        dto.Salary = payroll.Salary;
                    }
                    else
                    {
                        throw new Exception($"Author with ID = {id} was not found.");
                    }
                }
                else
                {
                    throw new Exception($"Payroll with ID = {id} was not found.");
                }
    
                return dto;
    
            }
    
            public async Task<DtoPayroll> FindPayRollByAuthorId(int id)
            {
                var dto = new DtoPayroll();
                
                var payroll = await pc.Payroll.Where(a =>a.AuthorId == id).SingleOrDefaultAsync();
    
                if (payroll != null)
                {
                    dto.PayRollId = payroll.PayrollId;
                }
    
                return dto;
            }
    
            public async Task Add(DtoPayroll dto)
            {
                var payroll = new Payroll
                {
                    AuthorId = dto.AuthorId,
                    Salary = dto.Salary
                };
    
                pc.Payroll.Add(payroll);
                await pc.SaveChangesAsync();
    
            }
    
            public async Task Update(DtoPayroll dto)
            {
                var payroll = new Payroll
                {
                    PayrollId = dto.PayRollId,
                    AuthorId = dto.AuthorId,
                    Salary = dto.Salary
                };
    
                pc.Entry(payroll).State = EntityState.Modified;
                await pc.SaveChangesAsync();
    
            }
    
            public async Task Delete(int id)
            {
                var payroll =  pc.Payroll.Find(id);
    
                if (payroll != null)
                {
                    pc.Payroll.Remove(payroll);
                    await pc.SaveChangesAsync();
                }
            }
    
        }
    }
    
    namespace Entities
    {
        public class DtoPayroll
        {
            public int PayRollId { get; set; }
            public int AuthorId { get; set; }
            public string AuthorFirstName { get; set; }
            public string AuthorLastName { get; set; }
            public int? Salary { get; set; }
        }
    }
    

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Friday, May 29, 2020 10:51 PM