开发者

MVC: How to factor Repository Interfaces based on multi-level object model

开发者 https://www.devze.com 2023-02-11 00:55 出处:网络
I\'ve got a multi level dependency chain in my object model: An organization has the following children relationships:

I've got a multi level dependency chain in my object model:

An organization has the following children relationships:

Organization
    .CompetitionGroups
    .CompetitionGroups.Venues
    .CompetitionGroups.Competitions
        .Divisions.Games
        .Divisions.Games.Participants
        .Divisions.Games.Participants.GameSegments
        .Divisions.SubDivisions...
        .Divisions
            .Teams
            .Teams.Players
            .Teams.Participants
            .Teams.Participants.GameSegments
        .VenueDates

This is just a glimpse at the object model, but it's focused on the complexity of the relationships and lists.

What I can't really get is what's the best way to factor my repository interfaces, given the requirements to do a unit of work.

For example, to create a game, you'll need a venuedate and two participants. Does that mean the GamesController should require an IGameRepository, an IVenueDateRepository, and an IParticipant repository? Should they be rolled into one repository?

Also, what about in the consumption cases? For example, to display a signle team's schedule, you'll need all of the Participants for that Team, all of the Games for that participant, and all of the GameSegments for the participant. If those are factored into individual repositories I can't see how you can do efficient queries.

Does that mean you have Repositories specifically focused on different cases? for example:

public interface IScheduleRepository {

    public ICollection<Game> GetScheduleForTeam(Team team);

    // More consumption methods
}

public class ScheduleRepositry : IScheduleRepository {

    public开发者_开发知识库 ScheduleRepository (ModelContext context) { 
        // Do stuff with context 
    }

    public ICollection<Game> GetScheduleForTeam(Team team) {

         return (
            from p in context.Participants
            where ((p.Game.VenueDate != null) &&
                (p.TeamId == team.Id))
            orderby p.Game.VenueDate.StartTime
            select p.Game).ToList();
    }

    // more consumption methods

}

public interface IGameRepository {

    public void AddGame(Game game);

    // More crud methods
}

// Not showing games repository

public class GamesController : Controller {

    public GamesController (IGameRepository gamesRepo, 
        IVenueDateRepository venueDateRepo,
        IParticipantRepository participantRepo) { 

        // do stuff with repos here 
    }

    [HttpPost]
    public ActionResult AddGame(Game game) {

         // Skipping validation logic
         // this?

         VenueDate = venueDateRepo.Add(game.VenueDate);
         foreach (Participant p in Game.Participants)
         {
             participantRepo.Add(p);
         }

         Game = gamesRepo.AddGame(game);

         // or this?
         // how would the game repo know to persist 
         // the children elements? is that tight coupling?

         Game = gamesRepo.AddGame(game);
    }

    // more consumption methods

}

My question is I don't yet understand to what degree factoring your repositories make sense based on a connected object model. I'd love to get some advice here.


You need to define your aggregate roots and boundaries, and then design your repositories around the roots.

There is a good (and brief) chapter on this in this book(free after registration)

As for doing a unit of work, I typically make this a function of the service layer. So a controller has a reference to the service, the service handles the orchestration between the repository(s), entity(s), unit of work etc.

0

精彩评论

暂无评论...
验证码 换一张
取 消