Repository pattern and localized lookup tables - c#

I am trying to grabs the idea of the pattern repository and trying to get it implemented in database structures I've already set up in the past. I'm now trying to get the best practice to work with my lookup tables. I've created a test project to play around and this is my database model:
You can see that I have three tables for the lookups: Lookup, Language and LookupLanguage. Language table simply contains the languages.
Lookup tables holds the different types used throughout the models.
And LookupLanguage links the both tables together:
I've created anew project with all the models 1 to 1 to the database tables:
I also created a generic repository and a generic CrudService interface:
public interface ICrudService<T> where T : IsActiveEntity, new()
{
int Create(T item);
void Save();
void Delete(int id);
T Get(int id);
IEnumerable<T> GetAll();
IEnumerable<T> Where(Expression<Func<T, bool>> func, bool showDeleted = false);
void Restore(int id);
}
Now, according to the following post: When implementing the repository pattern should lookup value / tables get their own Repository? , the repository should hide the underlying database layer. So I think I need a new implementation of a service and/or repository to get the lookups, but then, where do I have to tell in which language I need to have the lookup?
Let's take the status (new, accepted, refused) from the company as an example.
The company model is as follow:
public partial class Company : IsActiveEntity
{
[Required]
[MaxLength(50)]
public string CompanyName { get; set; }
public System.Guid StatusGuid { get; set; }
[ForeignKey("StatusGuid")]
public virtual Lookup Status { get; set; }
}
I guess I don't need to have a separate implementation of a repository?
But I need a separate implementation CompanyService.
interface ICompanyService : ICrudService<Company>
{
IQueryable<LookupLanguage> GetStatuses(Guid languageguid);
LookupLanguage GetStatus(Guid statusguid, Guid languageguid);
}
Is this the correct approach, or do I miss something here?

Creating a Generic LookupRepository in your case in a better option because of your table schema and maintainence perspective.
I'm not sure whether you are using both Service Locator and Repository pattern or just Repository because of the name ICompanyService. But regardless, I agree that Repositories should not represent tables 1-1 always but they do most of the times.
The SO link you provided has a different table structure than yours. You have a generic lookup table vs the link has a separate table for each lookup. In the case where you have separate tables it makes sense to have the lookup repository method go with the entity repository since you will have a separate code to fetch the data for each lookup(as they have separate tables with different schema).
But in you case you have a single table that stores all the lookup types for each language and it makes sense to have a single LookupRepository that returns all the various types of lookups based on Language and LookupType. If you create each lookup method in separate entity repositories (like GetStatuses in CompanyRepository and GetStatuses in ContactRepository) you will have to repeat the logic in the method for each repository.
Think if you change the schema of the lookup table (say add a column) and you want to test all places the lookups are used it will be nightmare if you have lookup methods all over the place and pretty easy if you have one method in LookupRepository.
interface ILookupService : ICrudService<Lookup>
{
IQueryable<Lookup> GetStatuses(Guid languageguid, LookupType lookupType);
Lookup GetStatus(Guid statusguid, Guid languageguid, LookupType lookupType);
}

As regards your question, "Is this the correct approach" - this entirely depends on your specific needs.
What you have done doesn't seem to have any real issues. You have implemented the repository pattern using generics which is great. You are using interfaces for your repositories which allows for easier unit testing, also great!
One of your tags seems to indicate you are interested in the Entity Framework. You do not seem to be using that. The Entity Framework would simplify your code by creating the boiler plate classes for you. You can still use your repository pattern code with the classes created by the Entity Framework.
It seems that you are confusing the idea of a service and a repository. A repository is a general object which allows you to get data from a store without caring about the implementation. In your example, ICompanyService is a repository.

It is really controversial topic and there are different approaches to this problem. In our data logic we are not using repository pattern because we do not want to abstract most of the benefits of Entity Framework. Instead, we pass the context to the business logic which is already a combination of UoW / Repository pattern. Your approach is okay if you are going this way on all of your company services. However what I have seen so far, putting methods to the related services by their return values is the best approach to remind where they are. For instance if you want to get the company lookup, create a ILookupService and put GetLookUpsByCompany(int companyId) method to retrieve the company lookups.

I would argue with the linked response. Repositories ARE linked to database entities, considering the Entity Framework itself as a uow/repository implementation is a best example. On the other hand, services are for domain concerns and if there is a mismatch between your database entities and domain entities (you have two separate layers), services can help to glue the two.
In your specific case, you have repositories although you call them services. And you need a repository per database entity, that's just easier to implement and maintain. And also it helps to answer your question: yes, you need the extra repository for the linking table.
A small suggestion. You seem to have a generic query function that only accepts where clauses
IEnumerable<T> Where(Expression<Func<T, bool>> func, bool showDeleted = false);
If you already follow this route that allows arbitrary filtering expressions (which itself is a little arguable as someone will point out that you can' possibly guarantee that all technically possible filters can be executed by the database engine), why don't you allow all possible queries, including ordering, paging, etc:
IQueryable<T> Query { get; }
This is as easy to implement as your version (you just expose the dbset) but allows clients to perform more complicated queries, with the same possible concern that such contract is possibly too broad.

Localization is a presentation layer thing. The lower layers of your application should bother with it as little as possible.
I see two different kind of lookups: translations of coded concepts (Mr/Miss/Mrs) and translations of entity properties (company name maybe, or job titles or product names).
Coded concepts
I would not use lookup tables for coded concepts. There is no need to bother the lower layers at all with this. You will only need to translate them once for the entire application and create simple resource files that contain the translations.
But if you do wish to keep the translations in the database, a separate lookup repository for the codes or even per code system will sort of replace the resource file and serve you fine.
Entity properties
I can imagine different/nastier localization issues when certain entities have one or more properties that get translated in different languages. Then, the translation becomes part of the entity. I'd want the repository to cough up entity objects that contain all translations of the description, in a dictionary or so. Cause the business layer should not worry about language when querying, caching and updating relations. It should not ask the company repository for the Dutch version of company X. It should simply ask for company X and be served a Company object that contains its name in Dutch, English and French.
I've one more remark about the actual database implementation:
I think the lookup tables are distracting from the actual entities, to the point where you have forgotten to create a relation between person and person company. ;) I'd suggest putting all translations of entity properties in a single XML type column instead.
This illustrates why the repository should handle entities plus translations. If you were to make this storage layer level implementation change at some point, i.e. go from lookup tables to xml columns, the repository interfaces should remain the same.

Related

Many-to-many relation with repository pattern in ASP.NET MVC

I am building an ASP.NET MVC application. My database has many-to-many relationship with a Intermediate table.
In my application, I am using repository pattern without Unit-Of-Work. I have a generic repository with CRUD operations defined in it.
Because I am using Entity Framework with a database-first approach, I have created my models from EDMX.
The intermediate table which I have is not showing up in .edmx file, but it is indicated by diamond sign so apparently that defines many to many.
This is an background to what I have. Now the issues
I have 2 tables Student & Books. In my view, I want a to display a form which has fields from both Student and Books table. Idea is each student will fill in their details and they will choose the books they are interested to read and then they will hit "Submit" upon submit their record should be save in my database and for admin I want all that record stored to be display for which I will use accordion to show the data. Because I am using generic repo at a time, I am injecting only one Student repo into my controller and upon form creation I only get data from Student table (i.e. their details) - I don't get fields from books where they can select the books.
Can someone please suggest me a solution?
For backup I am thinking if this doesn't work, I will get all the details in one single table in my database and use that. But I want to avoid that approach.
Any ideas, suggestions will be really helpful.
If you are using a Generic Repository pattern, then consider replacing it with a more purpose-built Repository class to serve the controller or service that wants to interact with the data domain. Generic Repositories, while extremely common out there in examples and such are an anti-pattern especially when it comes to Entity Framework. The reason is because they are poorly suited to the task and don't follow the intent of a Generic pattern. Generic classes are classes optimized where you can treat all instances entirely equally. This means if I have a Repository<Student> and a Repository<Book> then every operation between a Student and Book should be identical.
With EF, working on such assumptions is either crippling the capabilities that EF can bring, or adding a lot of unnecessary complexity to your solution to enable features like eager loading, filtering, projection, sorting, pagination, etc. While a Generic Repository can still serve as a base class for a repository, even then, the common capability that it can really provide doesn't really make it very worthwhile.
The other problem with Generic Repositories, or more specifically a Repository tied to a single Domain object is that it violates the Single Responsibility Principle. SRP is part of the S.0.L.I.D. design principles and states that a class should have one, and only one reason to change. While on the surface, using a Repository per domain object might seem like you're giving a repository one reason to change, this isn't really the case. Take something like a StudentRepository. How many controllers or services will need to interact with Students? Will they all be expecting to perform the exact same operations and have the exact same requirements of the Repository fetching and updating Students? Each consumer of a StudentRepository is a reason for that repository to change. One technique to get the most out of EF is to leverage Projection where-by we use Select or ProjectTo to significantly reduce the data size coming back and can leverage indexes for commonly used queries. If we are using a Generic Repository it's even worse because now the code in the repository has every reason to change as it needs to apply to all domain classes.
By all means you can write Generic Repositories or Repository-per-Domain Class to satisfy SRP, however the resulting Repository will either be extremely inefficient or extremely complex.
Instead, I recommend thinking of a Repository like you would a Controller in MVC, where a Repository has a single purpose: To Serve that Controller/Service.
For example, if I have a StudentController, I would create a StudentRepository. However, the purpose of StudentRepository is to serve the StudentController as opposed to the Student domain object. If the StudentController needs a list of Books, the StudentRepository will expose a method to retrieve them. A better example might be where I have a SearchStudentController and EditStudentController. Each of these would have respective SearchStudentRepository and EditStudentRepository. In this way the StudentRepository can expose methods specific to the needs of the Controller or Service that needs access to the domain. It has one, and only one reason to change.
The other advantage of this pattern is it makes dependency management a lot cleaner. Rather than a StudentController needing a StudentRepository, and a BookRepository, and a CourseRepository, and a ... It needs just one Repository to serve the domain.
There may be a legitimate case to have more common Repository available for things like lookup values or such that pretty much all similar Controllers or Services might consume where that consumption is identical across all controllers.
The counter-argument to this approach is that code can be duplicated. For instance if you have a BooksRepository for listing/adding/managing books and a StudentsRepository that also needs to list books, then you can end up with duplicate or similar code for something like:
IEnumerable<Book> GetBooks();
However, these methods are often "similar" rather than "identical". When you want a list of Books for a particular Student, chances are you are filtering out books that are applicable to their courses, or the current revision, etc. When you are listing Books on a book search and management screen you might want to see/filter books by completely different criteria.
So if in your case we have a StudentController and a non-Generic, Controller-serving StudentRepository class, when we want to get a list of students we can explore options that don't impact anything else. At a start we can consider something like:
public async Task<IEnumerable<Student>> GetStudents()
{
var students = await _context.Students
.Include(s => s.Books)
.ToListAsync();
return students;
}
Doing this with a Generic Repository isn't really viable, but with a Repository designed to serve our specific needs we can write queries that meet those needs.
For something like search results where we don't need every detail, the repository could return a simplified DTO with the details that need to be displayed. For instance if we just wanted the student's ID #, Name, and # of books:
[Serializable]
public class StudentSummaryDTO
{
public int StudentId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int BookCount { get; set; }
}
Then in the repository:
public async Task<IEnumerable<StudentSummaryDTO>> GetStudents()
{
var students = await _context.Students
.Select(s => new StudentSummaryDTO
{
StudentId = s.StudentId,
FirstName = s.FirstName,
LastName = s.LastName,
BookCount = s.Books.Count
}).ToListAsync();
return students;
}
This can generate a much faster and lighter weight query to run to return just enough data for the consumer. A more advanced variant is just to design the repository to return IQueryable<Student> to allow the consuming Controller to perform its own projection, pagination, etc.

DDD with EF Code First - how to put them together?

I am learning DDD development for few days, and i start to like it.
I (think i) understand the principle of DDD, where your main focus is on business objects, where you have aggregates, aggregates roots, repositories just for aggregates roots and so on.
I am trying to create a simple project where i combine DDD development with Code First approach.
My questions are: (I am using asp.net MVC)
DDD Business Objects will be different than Code First objects?
Even if they will probably be the same, for example i can have a Product business object which has all the rules and methods, and i can have a Product code first (POCO) object which will just contain the properties i need to save in database.
If answer to question 1 is "true", then how do i notify the Product POCO object that a property from business object Product has been changed and i have to update it? I am using an "AutoMapper" or something like this?
If the answer is "no", i am completely lost.
Can you show me the most simple (CRUD) example of how can i put those two together?
Thank you
Update I no longer advocate for the use of "domain objects" and instead advocate a use of a messaging-based domain model. See here for an example.
The answer to #1 is it depends. In any enterprise application, you're going to find 2 major categories of stuff in the domain:
Straight CRUD
There's no need for a domain object here because the next state of the object doesn't depend on the previous state of the object. It's all data and no behavior. In this case, it's ok to use the same class (i.e. an EF POCO) everywhere: editing, persisting, displaying.
An example of this is saving a billing address on an order:
public class BillingAddress {
public Guid OrderId;
public string StreetLine1;
// etc.
}
On the other hand, we have...
State Machines
You need to have separate objects for domain behavior and state persistence (and a repository to do the work). The public interface on the domain object should almost always be all void methods and no public getters. An example of this would be order status:
public class Order { // this is the domain object
private Guid _id;
private Status _status;
// note the behavior here - we throw an exception if it's not a valid state transition
public void Cancel() {
if (_status == Status.Shipped)
throw new InvalidOperationException("Can't cancel order after shipping.")
_status = Status.Cancelled;
}
// etc...
}
public class Data.Order { // this is the persistence (EF) class
public Guid Id;
public Status Status;
}
public interface IOrderRepository {
// The implementation of this will:
// 1. Load the EF class if it exists or new it up with the ID if it doesn't
// 2. Map the domain class to the EF class
// 3. Save the EF class to the DbContext.
void Save(Order order);
}
The answer to #2 is that the DbContext will automatically track changes to EF classes.
The answer is No. One of the best things about EF code-first is that it fits nicely with DDD since you have to create your business objects by hand so do use your EF models to be equivalent to DDD entities and value objects. No need to add an extra layer of complexity, I don't think DDD recommends that anywhere.
You could even have your entities to implement an IEntity and you value objects to implement IValue, additionally follow the rest of DDD patterns namely Repositories to do the actual communication to the database. More of these ideas you can find this very good sample application in .NET, even though it doesn't use EF code first, it's still very valuable: http://code.google.com/p/ndddsample/
Recently I've done similar project. I was following this tutorial: link
And I've done it this way: I've created Blank solution, added projects: Domain, Service and WebUI.
Simply said in domain I've put model (for example classes for EF code first, methods etc.)
Service was used for domain to communicate with world (WebUI, MobileUI, other sites etc.) using asp.net webapi
WebUi was actually MVC application (but model was in domain so it was mostly VC)
Hope I've helped
The Pluralsight course: Entity Framework in the Enterprise goes into this exact scenario of Domain Driven Design incorporated with EF Code First.
For number 1, I believe you can do it either way. It's just a matter of style.
For number 2, the instructor in the video goes through a couple ways to account for this. One way is to have a "State" property on every class that is set on the client-side when modifying a value. The DbContext then knows what changes to persist.
Late question on this topic.
Reading Josh Kodroff's answer confirms my thoughts about the implementation of a Repository to, for instance, Entity Framework DAL.
You map the domain object to an EF persistance object and let EF handle it when saving.
When retrieving, you let EF fetch from database and map it to your domain object(aggregate root) and adds it to your collection.
Is this the correct strategy for repository implementation?

Repository Pattern: How to implement a basic Repository including a predicate in C#?

I am new to repositories. I just read about implementing predicates and a Unit of Work (Fowler). I have seen repository interfaces like the following:
public interface IRepository<ET> {
ET Add( ET entity);
ET Remove( int id);
ET Get( int id);
IList<ET> Get(Expression<Func<T, bool>> predicate);
}
Of course the Unit of Work would inject a data context (Microsoft fan) to the new repository, where the Unit of Work would have a .Save() method, calling Save on all data contexts.
There's no Edit method, so I assume you can modify any Entity that pops out of the Repository then call save changes on the Unit of Work.
Is this correct? Leaky? What am I missing? Do methods of OrderBy need not ever be in a Repository? Should Paging (.Skip().Take()) somehow be implemented in the predicate?
Links to example code out there would be fantastic, especially how to implement the predicate in a repository.
if you are referring Entity Framework
i would you suggest you read this: Link
Update:
I am not a expert in repository pattern, however i do using it in my project now. a part form performance, following is the benefits that i find from this design pattern:
1, Simplify CRUD operation implementations for all entities.
with one interface:
public interface IDataRepository<T> where T : class
then you will be able to replicate others very easily and fast
public class EntityOneRepository : IDataRepository<EntityOne>
public class EntityTwoRepository : IDataRepository<EntityTwo>
2, Keeps my code dry.
some entities may have their own method for data manipulation. (i.e. store procedure)
you can extend it easily without touching other repositories.
public interface IDonationRepository : IDataRepository<Donation>
{
//method one
//method two
//....
}
for the Paging, it can be either done by Skip() and take(), or you can define your own SP in database then call it via EF4. in that case you will benefit from database sp caching as well.
Some time, keeping the code clean and logically readable is also important for a better app structure.
The repository interface you've presented is a very easy-to-use CRUD interface that can work well in many types of applications. In general, I'd rather not have paging and sorting parameters or options on my repository, instead I'd rather return an IQueryable and let callers compose those types of operations into the query (as long as you are IQueryable, a technology like EF or nHibernate can translate those operators into SQL - if you fall back to IList or IEnumerable it's all in memory operations).
Although I avoid paging and sorting I might have more specific operations on a repository to shield business logic from some details. For example, I might extend IEmployeeRepository from IRepository and add a GetManagers method, or something similar to hide the Where expression needed in the query. It all depends on the application and complexity level.
One important note on this sentence in your post:
Of course the Unit of Work would
inject a data context (Microsoft fan)
to the new repository, where the Unit
of Work would have a .Save() method,
calling Save on all data contexts.
Make sure you are using a single data context/object context inside each unit of work, because a context is essentially the underlying unit of work. If you are using multiple contexts in the same logic transaction then you'd effectively have multiple units of work.
I have a couple sample implementations in this project:
http://odetocode.com/downloads/employeetimecards.zip
The code might make more sense if you read this accompanying article:
http://msdn.microsoft.com/en-us/library/ff714955.aspx
Hope that helps,

Advice on Linq to SQL mapping object design

I hope the title and following text are clear, I'm not very familiar with the correct terms so please correct me if I get anything wrong. I'm using Linq ORM for the first time and am wondering how to address the following.
Say I have two DB tables:
User
----
Id
Name
Phone
-----
Id
UserId
Model
The Linq code generator produces a bunch of entity classes.
I then write my own classes and interfaces which wrap these Linq classes:
class DatabaseUser : IUser
{
public DatabaseUser(User user)
{
_user = user;
}
public Guid Id
{
get { return _user.Id; }
}
... etc
}
so far so good.
Now it's easy enough to find a users phones from Phones.Where(p => p.User = user) but surely comsumers of the API shouldn't need to be writing their own Linq queries to get at data, so I should wrap this query in a function or property somewhere.
So the question is, in this example, would you add a Phones property to IUser or not?
In other words, should my interface specifically be modelling my database objects (in which case Phones doesn't belong in IUser), or are they actually simply providing a set of functions and properties which are conceptually associated with a User (in which case it does)?
There seems drawbacks to both views, but I'm wondering if there is a standard approach to the problem. Or just any general words of wisdom you could share.
My first thought was to use extension methods but in fact that doesn't work in this case.
I've had some awful experiences trying to abstract LINQtoSQL entities behind interfaces. It was a while ago, but from memory the main problem was that it totally breaks associations. For example, if you have a Customer -> Order relationship, you end up exposing it as an ICustomer, with a collection of IOrders, which means that Customer has to do some awkward mapping to cast it's internal collection of Order objects as IOrders.
Then you have to assume that when an IOrder gets passed back in, that we can cast it to an Order. Otherwise LINQtoSQL can't deal with it, but then that defeats the point of having the interface there in the first place.
I would strongly recommend that you don't try and abstract away the entity classes too much, LINQtoSQL doesn't actually put any real magic in them, the DataContext handles their persistence lifecycle, so they remain testable.
The aspects that I would be looking to hide behind an interface would be the interactions with DataContext, for example using Repository-style classes:
public interface IPhoneRepository
{
IEnumerable<Phone> GetPhonesForUser(User user);
}
public class L2SPhoneRepository : IPhoneRepository
{
private readonly MyDataContext context;
public L2SPhoneRepository(MyDataContext context)
{
this.context = context;
}
public IEnumerable<Phone> GetPhonesForUser(User user)
{
return context.Phones.Where(p => p.User == user);
}
}
Your interface should model how you would like for the objects to be used. Since you are trying to abstract, then the consumer should not have to query the DB. Whether you make it a property, or a separate function call (ie, GetPhones()), is entirely up to you. Since you are completely wrapping things, you'll have to make some choices about how deep/lazily you want to load your objects.
You should add Phones property to IUser and make it nullable, so for a User who don't have Phone, it will be null.
Since you don't want consumers of the API to write queries, than you should implement functions like GetUser().. etc.
Here is a nice list of article abt n-tier application in Asp.net
http://imar.spaanjaars.com/QuickDocId.aspx?quickdoc=416
I tend to consider the Linq2Sql related stuff to be an implementation detail of the data access code and, like the real structure of the database, shouldn't necessarily be exposed to other parts of the system.
If your API is going to be consumed by other people it should be cohesive and easy to use and not cluttered by things the consumer doesn't need to know about. If I'm dealing with users and their phones I don't really want to know about DataContexts or (ugh) DataSets.
Also, by keeping the bulk of your code ignorant of the L2S and database you will have an easier time testing, making schema changes (oh, so now the User table needs to keep a history of every change made) or even changing the ORM completely.

ASP.NET MVC: How many repositories?

I am in the process is designing a website in ASP.NET MVC and am perhaps a little confused as to the exact nature of a repository.
Following the NerdDinner example, my site should have one repository which serves up the entities as I need them. However, I have also heard that you should have different repositorys that deal with specific sets of related entities....?
In the case of my site, there will be a number of entities (around 15 tables) yet the majority are all related. Is it ok / advisable to have one repository that contains all the methods that I'll need for pulling / updating / deleting etc or should I split them down?
I use a generic repository which is plenty for many entities.
For a more complex one, I simply extend this with what's needed. The best of both worlds really.
In domain driven design, there's a rule that repositories are per aggregate root. You can read more about it here.
The more I read, the more I think that NerdDinner is too often seen as a collection of good practices, while it's absolutely not (see here for a discussion of, particularly, NerdDinner repository). That's why people often blame other MS examples like Oxite (and here:
Developers will flock to it, praise
it, and blindly accept it as gospel
because it comes from Microsoft (it's
already well on its way). Sadly, any
developer which adopts its spirit will
be left with an unmaintainble,
untestable and unreadable mess
).
If you use a generic repository which accepts types then I don't see any reason to use more than one.
we use an interface like this:
public interface IRepository
{
void Save<ENTITY>(ENTITY entity)
where ENTITY : Entity;
void Delete<ENTITY>(ENTITY entity)
where ENTITY : Entity;
ENTITY Load<ENTITY>(int id)
where ENTITY : Entity;
IQueryable<ENTITY> Query<ENTITY>()
where ENTITY : Entity;
IList<ENTITY> GetAll<ENTITY>()
where ENTITY : Entity;
IQueryable<ENTITY> Query<ENTITY>(IDomainQuery<ENTITY> whereQuery)
where ENTITY : Entity;
ENTITY Get<ENTITY>(int id) where ENTITY : Entity;
IList<ENTITY> GetObjectsForIds<ENTITY>(string ids) where ENTITY : Entity;
void Flush();
}
then use in code like this:
var returnedObjects = repository.GetAll<ObjectClass>();
var singleObject = repository.Get<ObjectClass>(id);
I create a repository for each data object.
For example, a simple library database could contain the following repositories:
AuthorRepository
BookRepository
PublisherRepository
I think perhaps the verbiage of what is a repository might be confusing you. To me a repository is the data storage (ie; MS SQL Database) of where your data is being stored into.
Following the Repository Pattern I recommend setting up a single respository for each datastore. Most of my projects I use MS SQL so I create a Repository for that DB (I like using Subsonic for my DAL/ORM and it also implements the Repositry pattern and the ActiveRecord pattern) then I create Factories for each table. This lets me wrap up the Subsonic ActiveREcord classes and gives me abstraction.
Hope thats helpfull, perhaps...
You should not create Repositories per each table. As queen3 said, you should create Repository per aggregate root. Like, if Products can have a Category, Category Repository should be a nested class of Products. Follow the domain logic relationship than domain objects.
Queen3 is right, you can follow that Aggregate Root theory. I basically group my repository not thinking in Entities but how they group logically in the application I'm building.
For example:
CustomersRepository
OrdersRepository
...
In CustomerRepository I would put methods for GetCustomers, GetCustomer, AddCustomer, DeleteCustomer, AddCustomerContact, DeleteCustomerContact.
In OrdersRepository I would put methods for GetOrders, GetOrder, AddOrder, CancelOrder, CloneOrder, AddOrderDetail, DeleteOrderDetail and so on.
I tend to use a repository per related group of entitites. i.e orderrepository might have:
Order, and OrderDetail.
and would have another for, say, Customer, CustomerProfile, etc.
This keeps the repository classes neat.
Davy

Categories

Resources