Click here to Skip to main content
15,914,165 members
Home / Discussions / Design and Architecture
   

Design and Architecture

 
GeneralRe: Python: how doI "select / switch in" a module/class to use at runtime Pin
ninjaef3-Jul-18 3:24
ninjaef3-Jul-18 3:24 
GeneralRe: Python: how doI "select / switch in" a module/class to use at runtime Pin
Richard MacCutchan3-Jul-18 4:26
mveRichard MacCutchan3-Jul-18 4:26 
GeneralRe: Python: how doI "select / switch in" a module/class to use at runtime Pin
ninjaef3-Jul-18 7:14
ninjaef3-Jul-18 7:14 
GeneralRe: Python: how doI "select / switch in" a module/class to use at runtime Pin
Richard MacCutchan3-Jul-18 8:25
mveRichard MacCutchan3-Jul-18 8:25 
QuestionMy Entity Framework Design Pin
Kevin Marois2-Jul-18 7:14
professionalKevin Marois2-Jul-18 7:14 
AnswerRe: My Entity Framework Design Pin
Richard Deeming2-Jul-18 8:17
mveRichard Deeming2-Jul-18 8:17 
GeneralRe: My Entity Framework Design Pin
Kevin Marois2-Jul-18 8:30
professionalKevin Marois2-Jul-18 8:30 
GeneralRe: My Entity Framework Design Pin
Richard Deeming2-Jul-18 9:00
mveRichard Deeming2-Jul-18 9:00 
I think there's still room for improvement. Smile | :)

Your classes are currently tied to specific implementations, which would make it harder to test them.

Perhaps try something like this:
C#
interface IUnitOfWork : IDisposable
{
    void Save();
    Task SaveAsync();
}

// NB: Could implement the IUnitOfWork interface directly on the FalconContext class.
class FalconContextUnitOfWork : IUnitOfWork
{
    private readonly FalconContext _context;
    
    public FalconContextUnitOfWork(FalconContext context)
    {
        _context = context;
    }
    
    public void Save()
    {
        _context.SaveChanges();
    }
    
    public Task SaveAsync()
    {
        return _context.SaveChangesAsync();
    }
    
    public void Dispose()
    {
        _context.Dispose();
    }
}

interface IBizObject : IDisposable
{
    void AddProject(Project entity);
}

class BizObject : IBizObject
{
    private readonly IProjectsRepository _projectsRepository;
    private readonly IProjectsTaskRepository _projectsTaskRepository;
    private readonly IUnitOfWork _unitOfWork;
    
    public BizObject(IProjectsRepository projectsRepository, IProjectsTaskRepository projectsTaskRepository, IUnitOfWork unitOfWork)
    {
        _projectsRepository = projectsRepository;
        _projectsTaskRepository = projectsTaskRepository;
        _unitOfWork = _unitOfWork;
    }
    
    public void AddProject(Project entity)
    {
        if (_projectsRepository.FindProjectsByName(entity.ProjectName).Any())
        {
            throw new DuplicateProjectException(entity.ProjectName);
        }
        
        _projectsRepository.Add(entity);

        foreach (var task in entity.Tasks)
        {
            _projectsTaskRepository.Add(task);
        }
        
        _unitOfWork.Save();
    }
    
    public void Dispose()
    {
        _unitOfWork.Dispose();
    }
}

public class ProjectsController : ApiController
{
    private IBizObject _bo;
    
    public ProjectsController(IBizObject bo)
    {
        _bo = bo;
    }

    public IHttpActionResult AddProject(Project entity)
    {
        _bo.AddProject(entity);
        return Ok();
    }
    
    protected override void Dispose(bool disposing)
    {
        base.Dispose(disposing);
        if (disposing) _bo.Dispose();
    }
}

Register all of the concrete implementations as transient services in your DI container. You should then get a new instance of all three classes for each request, but sharing the same instance of your DbContext between them.

In your unit tests, you can pass specific mocks of the interfaces to the constructor of the class you're testing.

Implementing the Repository and Unit of Work Patterns in an ASP.NET MVC Application (9 of 10) | Microsoft Docs[^]



"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer

GeneralRe: My Entity Framework Design Pin
Kevin Marois2-Jul-18 10:15
professionalKevin Marois2-Jul-18 10:15 
GeneralRe: My Entity Framework Design Pin
Kevin Marois4-Jul-18 17:33
professionalKevin Marois4-Jul-18 17:33 
GeneralRe: My Entity Framework Design Pin
Richard Deeming5-Jul-18 1:27
mveRichard Deeming5-Jul-18 1:27 
GeneralRe: My Entity Framework Design Pin
Kevin Marois9-Jul-18 6:17
professionalKevin Marois9-Jul-18 6:17 
GeneralRe: My Entity Framework Design Pin
Kevin Marois9-Jul-18 6:19
professionalKevin Marois9-Jul-18 6:19 
GeneralRe: My Entity Framework Design Pin
Richard Deeming9-Jul-18 8:20
mveRichard Deeming9-Jul-18 8:20 
GeneralRe: My Entity Framework Design Pin
Kevin Marois16-Jul-18 6:28
professionalKevin Marois16-Jul-18 6:28 
GeneralRe: My Entity Framework Design Pin
Richard Deeming16-Jul-18 8:16
mveRichard Deeming16-Jul-18 8:16 
QuestionEntity Framework Question Pin
Kevin Marois29-Jun-18 9:31
professionalKevin Marois29-Jun-18 9:31 
AnswerRe: Entity Framework Question Pin
Richard Deeming29-Jun-18 10:02
mveRichard Deeming29-Jun-18 10:02 
AnswerRe: Entity Framework Question Pin
Gerry Schmitz29-Jun-18 11:01
mveGerry Schmitz29-Jun-18 11:01 
GeneralRe: Entity Framework Question Pin
Kevin Marois29-Jun-18 11:26
professionalKevin Marois29-Jun-18 11:26 
GeneralRe: Entity Framework Question Pin
Gerry Schmitz29-Jun-18 11:59
mveGerry Schmitz29-Jun-18 11:59 
AnswerRe: Entity Framework Question Pin
jschell30-Jun-18 5:35
jschell30-Jun-18 5:35 
AnswerRe: Entity Framework Question Pin
Mycroft Holmes30-Jun-18 13:23
professionalMycroft Holmes30-Jun-18 13:23 
QuestionQuestions About Entity Framework and the Repository Pattern Pin
Kevin Marois29-Jun-18 5:28
professionalKevin Marois29-Jun-18 5:28 
AnswerRe: Questions About Entity Framework and the Repository Pattern Pin
Nathan Minier29-Jun-18 7:34
professionalNathan Minier29-Jun-18 7:34 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.