Niklas
Niklas

Reputation: 13155

Creating new repositories with each controller

I've been reading up on Dependency Incection, UnitOfWork and IRepository patterns, and I intend to implement them all as I go along. But it's all a lot to take in at once. Right now I just want to make sure about some basic things, and that I'm not missing anything crucial that could impact my application.

The application is rather small and there will be no more than 10 simultaneous users at any given point.

The AdressRegDataContext is the dbml generated (using Visual Studio Add -> Linq to SQL classes).

My question concern the adding of the second controller below:

To me it feels like two users would have two different contexts if they are using the application at the same time. Or do the datacontext handle that for me? A singleton repository makes sense theoretically, but I've read that that's a big nono so I won't do that.

I have a repository that I use:

Repository

namespace AdressReg.Models
{
    public class AdressRegRepository
    {
        private AdressRegDataContext db = new AdressRegDataContext();

        // Return person by id
        public Person GetPerson(int id)
        {
            return db.Persons.SingleOrDefault(p => p.id == id);
        }

        // Return student by id
        public Student GetStudent(int id)
        {
            return db.Students.SingleOrDefault(s => s.id == id);
        }
    }
}

So far I've only been using the one controller:

HomeController

namespace AdressReg.Controllers
{
    public class HomeController : Controller
    {
        AdressRegRepository repository = new AdressRegRepository();

        // GET: /Home/Person
        public ActionResult Person(int id)
        {
            PersonView view = new PersonView();
            view.person = repository.GetPerson(id);

            return View(view);
        }
    }
}

But I was planning on adding another:

EducationController

namespace AdressReg.Controllers
{
    public class EducationController: Controller
    {
        AdressRegRepository repository = new AdressRegRepository();

        // GET: /Education/Student
        public ActionResult Student(int id)
        {
            StudentView view = new StudentView();
            view.student = repository.GetStudent(id);

            return View(view);
        }
    }
}

Upvotes: 0

Views: 328

Answers (1)

MikeSW
MikeSW

Reputation: 16378

Yes they are. First of all that's not a 'true' repository, that is a useless abstraction on top of EF, you can ditch it. A repository should return busines or app objects not EF entities. For querying purposes it should return at least some bits (if not all ) of the view model. So, it should return a PersonView or a StudentView. These are guideliness not the absolute truth or rules, but you really need to be aware of the purpose of a design pattern, in this case the Repository. And your code shows you haven't understood it yet.

In your app, the repo doesn't do anything useful, so use the ORM directly, it's much simpler.

Your controllers are tightly coupled to a specific concrete repository. The point is you should define an abstraction and pass that as a dependency in the constructor. Something like

 // a better name is needed, this would be a query repository
public interface IAddressesRegRepository
{
    StudentView Get(int it);
}

public class MyController:Controller
{
    IAddressesRegRepository _repo;   
    public MyController(IAddressesRegRepository repo) 
    {
        _repo=repo;
     }

     public ActionResult Student(int id)
    {
        StudentView view = _repo.GetStudent(id);

        return View(view);
    }

 }

As you see, the controller now depends on an abstraction, the DI Container will inject a concrete implementation when the controller is created. It will allow you to mock repositories and to have multiple implementations. Same approach is for everything you want to use in the controller.

About repositories, I do prefer to have different business/ query repositories (though nowadays I'm using query handlers) i.e I don't put querying behaviour on a domain repository unless it's needed by the business layer itself.

For strictly querying, it's much straight forward to use EF or if your queries are ugly or want to change implementation later, use a query object/ repository/service/handler (call it however you want) that will construct the view model from persistence. The point is to keep the persistence details (ORM, EF Entites) in the DAL, your UI shouldn't know about them. In your example, the UI knows about EF entites.

Once again, what I've said are guidelines, when you get more experienced you'll know when to bend (break) them without nasty side effects.

Upvotes: 1

Related Questions