I'm wondering what the recommended approach is for dealing with relational data with the IRepository pattern.
My database has the following tables with column names in parenthesis:
Where each plan can have zero or many Areas but only one view, so Plans.ViewId is FK to Views.ViewId. In PlanAreas, both columns are FK to the respective tables.
There are times when my application might want to act independently on the areas, but usually I will be loading, saving, deleting a plan and all of its constituents (areas, views) at the same time.
I've started down the path ....
public interface IPlanRepository
{
IEnumerable<MyModel.Plan> GetAll();
MyModel.Plan GetByName(string sName);
MyModel.Plan GetById(string sId);
void Delete(MyModel.Plan plan);
void SaveOrUpdate(MyModel.Plan plan);
}
public class Plan
{
public Guid Id { get; set; }
public string Name { get; set; }
public DateTime Creation { get; set; }
public DateTime Modified { get; set; }
public MyModel.View View { get; set; }
public IList<MyModel.Area> Areas { get; set; }
}
public class View
{
public Guid Id { get; set; }
public IEnvelope Envelope { get; set; } // encapsulates top, left, bottom, right
}
// etc.
The plan is fairly complex, so there will actually be more properties, but this is a good start. So now for the questions:
Or is it better to have a higher-level "aggregator" (for lack of a better word) that will fill in the properties once the Plan is returned? Something like this:
Plan GetPlanById(string sId)
{
Plan myplan = new Plan();
IPlanRepository planrepo = new PlanRepoImpl();
myplan = planrepo.GetById(sId);
IViewRepository viewrepo = new ViewRepoImpl();
myplan.View = viewrepo.GetByPlanId(sId);
return myplan;
}
Right now I'm planning on using LINQ-SQL for my data access because I'm familiar with it, and I can do it fairly quickly. I may switch to something else down the line, but I want to keep it simple for now.
If you don't do a repo for the sub parts of the plan, how do you handle loading only the parts you need? If, for example, I wanted to get a list of all the plans in the system and choose one to view in detail you absolutely don't want to return fully populated plan object just to show a summary list. That would kill performance in so many ways. Instead you'd just want a lean plan object and maybe the count of how many areas it had (rather than all the fully populated areas). And, on top of it, you'd want to do all this in a reusable generic fashion.
I would lean toward the notion of separate repositories for each prime entity you wanted to work with. Then manage relationships between those through some sort of aggregator. Or, perhaps you pass a list of property references and associated delegates (or expression trees) to each retrieval method on your aggregate root repo to tell it which items to fill. But you still have the issue of 2nd level, third level, 4th level, etc. relationships. Back to the original idea of just needing to show a list of plans and a count of the areas...you wouldn't want to return all the area to just get a count.
And that's just retrieval. What if your Plan had 5 Areas and each Area had a series of Envelopes and you decided to add, edit, or delete an Envelope from an Area. How would you walk the tree to figure out what to update when you're at the Plan level? Seems it would make more sense to manipulate an Envelope through and Envelope repo.
It seems to me the repo handles data retrieval and another engine/class handles relationship fixup.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With