Should repositories expose IQueryable to service layer or perform filtering in the implementation? - linq-to-sql

I'm trying to decide on the best pattern for data access in my MVC application.
Currently, having followed the MVC storefront series, I am using repositories, exposing IQueryable to a service layer, which then applies filters. Initially I have been using LINQtoSQL e.g.
public interface IMyRepository
{
IQueryable<MyClass> GetAll();
}
Implemented in:
public class LINQtoSQLRepository : IMyRepository
{
public IQueryable<MyClass> GetAll()
{
return from table in dbContext.table
select new MyClass
{
Field1 = table.field1,
... etc.
}
}
}
Filter for IDs:
public static class TableFilters
{
public static MyClass WithID(this IQueryable<MyClass> qry, string id)
{
return (from t in qry
where t.ID == id
select t).SingleOrDefault();
}
}
Called from service:
public class TableService
{
public MyClass RecordsByID(string id)
{
return _repository.GetAll()
.WithID(id);
}
}
I ran into a problem when I experimented with implementing the repository using Entity Framework with LINQ to Entities. The filters class in my project contains some more complex operations than the "WHERE ... == ..." in the example above, which I believe require different implementations depending on the LINQ provider. Specifically I have a requirement to perform a SQL "WHERE ... IN ..." clause. I am able to implement this in the filter class using:
string[] aParams = // array of IDs
qry = qry.Where(t => aParams.Contains(t.ID));
However, in order to perform this against Entity Framework, I need to provide a solution such as the BuildContainsExpression which is tied to the Entity Framework. This means I have to have 2 different implementations of this particular filter, depending on the underlying provider.
I'd appreciate any advice on how I should proceed from here.
It seemed to me that exposing an IQueryable from my repository, would allow me to perform filters on it regardless of the underlying provider, enabling me to switch between providers if and when required. However the problem I describe above makes me think I should be performing all my filtering within the repositories and returning IEnumerable, IList or single classes.
Many thanks,
Matt

This is a very popular question. One that I constantly ask myself. I've always felt it best to return IEnumerable rather than IQueryable from a repository.
The purpose of a repository is to encapsulate the database infrastructure so the client need not worry about the data source. However, if you return IQueryable you are at the mercy of the consumer as to what kind of query will get run against your db, and whether they will do something that the LINQ provider doesn't support.
Take paging for example. Lets say you have a Customer entity and your database could have hundreds of thousands of customers. Which code would you rather have your client write?
var customers = repos.GetCustomers().Skip(skipCount).Take(pageSize).ToList();
OR
var customers = repos.GetCustomers(pageIndex, pageSize);
In the first approach you make it impossible for the repository to restrict the number of records retrieved from the data source. Also, your consumer has to calculate the skipCount.
In the second approach you provide a more coarse grained interface to your client. Now your repository can enforce some constraints on the pageSize in order to optimize the query. You also encapsulate the calculation of the skipCount.
However, that being said, in your situation your client is your service. So I suppose the question really comes down to a separation of concerns. Where is it better to perform such validation logic? Well that answer may very well be "in the service". But what about the answer to "Where is it better to contain query logic?". To me the answer is clearly "The Repository". That is its intended area of expertise.

Related

Should I return IEnumerable<T> or IQueryable<T> from my DAL?

I know this could be opinion, but I'm looking for best practices.
As I understand, IQueryable<T> implements IEnumerable<T>, so in my DAL, I currently have method signatures like the following:
IEnumerable<Product> GetProducts();
IEnumerable<Product> GetProductsByCategory(int cateogoryId);
Product GetProduct(int productId);
Should I be using IQueryable<T> here?
What are the pros and cons of either approach?
Note that I am planning on using the Repository pattern so I will have a class like so:
public class ProductRepository {
DBDataContext db = new DBDataContext(<!-- connection string -->);
public IEnumerable<Product> GetProductsNew(int daysOld) {
return db.GetProducts()
.Where(p => p.AddedDateTime > DateTime.Now.AddDays(-daysOld ));
}
}
Should I change my IEnumerable<T> to IQueryable<T>? What advantages/disadvantages are there to one or the other?
It depends on what behavior you want.
Returning an IList<T> tells the caller that they've received all of the data they've requested
Returning an IEnumerable<T> tells the caller that they'll need to iterate over the result and it might be lazily loaded.
Returning an IQueryable<T> tells the caller that the result is backed by a Linq provider that can handle certain classes of queries, putting the burden on the caller to form a performant query.
While the latter gives the caller a lot of flexibility (assuming your repository fully supports it), it's the hardest to test and, arguably, the least deterministic.
One more thing to think about: where is your paging/sorting support? If you are providing paging support within your repository, returning IEnumerable<T> is fine. If you are paging outside of your repository (like in the controller or service layer) then you really want to use IQueryable<T> because you don't want to load the entire dataset into memory before it's paged.
HUUUUGGGE difference. I see this quite a bit.
You build up an IQueryable before it hits the database. The IQueryable only hits the DB once an eager function is called (.ToList() for example) or you actually try to pull values out. IQueryable = lazy.
An IEnumerable will execute your lambda against the DB right away. IEnumerable = eager.
As for which to use with the Repository pattern, I believe it's eager. I usually see ILists being passed but someone else will need to iron that out for you. EDIT - You usually see IEnumerable instead of IQueryable because you don't want layers past your Repository A) determining when the database hit will happen or B) Adding any logic to the joins outside the Repository
There is a very good LINQ video that I enjoy a lot- it hits more than just IEnumerable v IQueryable, but it really has some fantastic insight.
http://channel9.msdn.com/posts/matthijs/LINQ-Tips-Tricks-and-Optimizations-by-Scott-Allen/
You can use IQueryable and accept that someone could create a scenario where a SELECT N+1 could happen. This is a disadvantage, along with the fact that you may end up with code that is specific to your repository implementation in the layers above your repository. The advantage of this is that you are allowing the delegation common operations like paging and sorting to be expressed outside of your respository, therefore alleviating it of such concerns. It is also more flexible if you need to join the data with other database tables, as the query will remain an expression, so can be added to before its resolved into a query and hits the database.
The alternative is to lock down your repository so that it returns materialised lists by calling ToList(). With the example of paging and sorting, you will need to pass in skip, take and a sort expression as parameters to the methods of your repository, and use the parameters to return only a window of results. This means that the repository is taking on the responsibility of paging and sorting, and all of the projection of your data.
This is a bit of a judgement call, do you give your application the power of linq, and have less complexity in the repository, or do you control your data access. For me it depends on the number of queries associated with each entity, and combinations of entities, and where I want to manage that complexity.

Does AutoMapper support Linq?

I am very interested in Linq to SQL with Lazy load feature. And in my project I used AutoMapper to map DB Model to Domain Model (from DB_RoleInfo to DO_RoleInfo). In my repository code as below:
public DO_RoleInfo SelectByKey(Guid Key)
{
return SelectAll().Where(x => x.Id == Key).SingleOrDefault();
}
public IQueryable<DO_RoleInfo> SelectAll()
{
Mapper.CreateMap<DB_RoleInfo, DO_RoleInfo>();
return from role in _ctx.DB_RoleInfo
select Mapper.Map<DB_RoleInfo, DO_RoleInfo>(role);
}
SelectAll method is run well, but when I call SelectByKey, I get the error:
Method “RealMVC.Data.DO_RoleInfo MapDB_RoleInfo,DO_RoleInfo” could not translate to SQL.
Is it that Automapper doesn't support Linq completely?
Instead of Automapper, I tried the manual mapping code below:
public IQueryable<DO_RoleInfo> SelectAll()
{
return from role in _ctx.DB_RoleInfo
select new DO_RoleInfo
{
Id = role.id,
name = role.name,
code = role.code
};
}
This method works the way I want it to.
While #Aaronaught's answer was correct at the time of writing, as often the world has changed and AutoMapper with it. In the mean time, QueryableExtensions were added to the code base which added support for projections that get translated into expressions and, finally, SQL.
The core extension method is ProjectTo1. This is what your code could look like:
using AutoMapper.QueryableExtensions;
public IQueryable<DO_RoleInfo> SelectAll()
{
Mapper.CreateMap<DB_RoleInfo, DO_RoleInfo>();
return _ctx.DB_RoleInfo.ProjectTo<DO_RoleInfo>();
}
and it would behave like the manual mapping. (The CreateMap statement is here for demonstration purposes. Normally, you'd define mappings once at application startup).
Thus, only the columns that are required for the mapping are queried and the result is an IQueryable that still has the original query provider (linq-to-sql, linq-to-entities, whatever). So it is still composable and this will translate into a WHERE clause in SQL:
SelectAll().Where(x => x.Id == Key).SingleOrDefault();
1 Project().To<T>() prior to v. 4.1.0
Change your second function to this:
public IEnumerable<DO_RoleInfo> SelectAll()
{
Mapper.CreateMap<DB_RoleInfo, DO_RoleInfo>();
return from role in _ctx.DB_RoleInfo.ToList()
select Mapper.Map<DB_RoleInfo, DO_RoleInfo>(role);
}
AutoMapper works just fine with Linq to SQL, but it can't be executed as part of the deferred query. Adding ToList() at the end of your Linq query causes it to immediately evaluate the results, instead of trying to translate the AutoMapper segment as part of the query.
Clarification
The notion of deferred execution (not "lazy load") does not make any sense once you've changed the resulting type to something that's not a data entity. Consider these two classes:
public class DB_RoleInfo
{
public int ID { get; set; }
public string Name { get; set; }
}
public class DO_RoleInfo
{
public Role Role { get; set; } // Enumeration type
}
Now consider the following mapping:
Mapper.CreateMap<DB_RoleInfo, DO_RoleInfo>
.ForMember(dest => dest.Role, opt => opt.MapFrom(src =>
(Role)Enum.Parse(typeof(Role), src.Name)));
This mapping is completely fine (unless I made a typo), but let's say you write the SelectAll method in your original post instead of my revised one:
public IQueryable<DO_RoleInfo> SelectAll()
{
Mapper.CreateMap<DB_RoleInfo, DO_RoleInfo>();
return from role in _ctx.DB_RoleInfo
select Mapper.Map<DB_RoleInfo, DO_RoleInfo>(role);
}
This actually kind of works, but by calling itself a "queryable", it lies. What happens if I try to write this against it:
public IEnumerable<DO_RoleInfo> SelectSome()
{
return from ri in SelectAll()
where (ri.Role == Role.Administrator) ||
(ri.Role == Role.Executive)
select ri;
}
Think really hard about this. How could Linq to SQL possibly be able to successfully turn your where into an actual database query?
Linq knows nothing about the DO_RoleInfo class. It doesn't know how to do the mapping backward - in some cases, that may not even possible. Sure, you may look at this code and go "Oh, that's easy, just search for 'Administrator' or 'Executive' in the Name column", but you're the only one who knows that. As far as Linq to SQL is concerned, the query is pure nonsense.
Imagine that somebody gave you these instructions:
Go to the supermarket and bring back the ingredients for making Morton Thompson Turkey.
Unless you've made it before, and most people haven't, your response to that instruction is most likely going to be:
What the hell is that?
You can go to the market, and you can get specific ingredients by name, but you can't evaluate the condition I've given you while you're over there. I have to "un-map" the criteria first. I have to tell you, here are the ingredients we need for this recipe - now go and get them.
To summarize, this is not some simple incompatibility between Linq to SQL and AutoMapper. It is not unique to either of those two libraries. It doesn't matter how you actually do the mapping to a non-entity type - you could just as easily do the mapping manually, and you'd still get the same error, because you are now giving Linq to SQL a set of instructions that are no longer comprehensible, dealing with mysterious classes that don't have an intrinsic mapping to any particular entity type.
This issue is fundamental to the concept of O/R Mapping and deferred query execution. A projection is a one-way operation. Once you project, you can no longer go back to the query engine and say oh by the way, here are some more conditions for you. It's too late. The best you can do is take what it already gave you and evaluate the extra conditions yourself.
Last but not least, I'll leave you with a workaround. If the only thing you want to be able to do from your mapping is filter the rows, you can write this:
public IEnumerable<DO_RoleInfo> SelectRoles(Func<DB_RoleInfo, bool> selector)
{
Mapper.CreateMap<DB_RoleInfo, DO_RoleInfo>();
return _ctx.DB_RoleInfo
.Where(selector)
.Select(dbr => Mapper.Map<DB_RoleInfo, DO_RoleInfo>(dbr));
}
This is a utility method that handles the mapping for you and accepts a filter on the original entity, and not the mapped entity. It might be useful if you have many different kinds of filters but always need to do the same mapping.
Personally, I think you will be better off just writing out the queries properly, by first determining what you need to retrieve from the database, then doing any projections/mappings, and then, finally, if you need to do further filtering (which you shouldn't), then materialize the results with ToList() or ToArray() and write more conditions against the local list.
Don't try to use AutoMapper or any other tool to hide the real entities exposed by Linq to SQL. The domain model is your public interface. The queries you write are an aspect of your private implementation. It's important to understand the difference and maintain a good separation of concerns.

How do you implement Pipes and Filters pattern with LinqToSQL/Entity Framework/NHibernate?

While building by DAL Repository, I stumbled upon a concept called Pipes and Filters. I read about it here, here and saw a screencast from here. I am still not sure how to go about implementing this pattern. Theoretically all sounds good , but how do we really implement this in an enterprise scenario?
I will appreciate, if you have any resources,tips or examples ro explanation for this pattern in context to the data mappers/ORM mentioned in the question.
Thanks in advance!!
Ultimately, LINQ on IEnumerable<T> is a pipes and filters implementation. IEnumerable<T> is a streaming API - meaning that data is lazily returns as you ask for it (via iterator blocks), rather than loading everything at once, and returning a big buffer of records.
This means that your query:
var qry = from row in source // IEnumerable<T>
where row.Foo == "abc"
select new {row.ID, row.Name};
is:
var qry = source.Where(row => row.Foo == "abc")
.Select(row = > new {row.ID, row.Name});
as you enumerate over this, it will consume the data lazily. You can see this graphically with Jon Skeet's Visual LINQ. The only things that break the pipe are things that force buffering; OrderBy, GroupBy, etc. For high volume work, Jon and myself worked on Push LINQ for doing aggregates without buffering in such scenarios.
IQueryable<T> (exposed by most ORM tools - LINQ-to-SQL, Entity Framework, LINQ-to-NHibernate) is a slightly different beast; because the database engine is going to do most of the heavy lifting, the chances are that most of the steps are already done - all that is left is to consume an IDataReader and project this to objects/values - but that is still typically a pipe (IQueryable<T> implements IEnumerable<T>) unless you call .ToArray(), .ToList() etc.
With regard to use in enterprise... my view is that it is fine to use IQueryable<T> to write composable queries inside the repository, but they shouldn't leave the repository - as that would make the internal operation of the repository subject to the caller, so you would be unable to properly unit test / profile / optimize / etc. I've taken to doing clever things in the repository, but return lists/arrays. This also means my repository stays unaware of the implementation.
This is a shame - as the temptation to "return" IQueryable<T> from a repository method is quite large; for example, this would allow the caller to add paging/filters/etc - but remember that they haven't actually consumed the data yet. This makes resource management a pain. Also, in MVC etc you'd need to ensure that the controller calls .ToList() or similar, so that it isn't the view that is controlling data access (otherwise, again, you can't unit test the controller properly).
A safe (IMO) use of filters in the DAL would be things like:
public Customer[] List(string name, string countryCode) {
using(var ctx = new CustomerDataContext()) {
IQueryable<Customer> qry = ctx.Customers.Where(x=>x.IsOpen);
if(!string.IsNullOrEmpty(name)) {
qry = qry.Where(cust => cust.Name.Contains(name));
}
if(!string.IsNullOrEmpty(countryCode)) {
qry = qry.Where(cust => cust.CountryCode == countryCode);
}
return qry.ToArray();
}
}
Here we've added filters on-the-fly, but nothing happens until we call ToArray. At this point, the data is obtained and returned (disposing the data-context in the process). This can be fully unit tested. If we did something similar but just returned IQueryable<T>, the caller might do something like:
var custs = customerRepository.GetCustomers()
.Where(x=>SomeUnmappedFunction(x));
And all of a sudden our DAL starts failing (cannot translate SomeUnmappedFunction to TSQL, etc). You can still do a lot of interesting things in the repository, though.
The only pain point here is that it might push you to have a few overloads to support different calling patterns (with/without paging, etc). Until optional/named parameters arrives, I find the best answer here is to use extension methods on the interface; that way, I only need one concrete repository implementation:
class CustomerRepository {
public Customer[] List(
string name, string countryCode,
int? pageSize, int? pageNumber) {...}
}
interface ICustomerRepository {
Customer[] List(
string name, string countryCode,
int? pageSize, int? pageNumber);
}
static class CustomerRepositoryExtensions {
public static Customer[] List(
this ICustomerRepository repo,
string name, string countryCode) {
return repo.List(name, countryCode, null, null);
}
}
Now we have virtual overloads (as extension methods) on ICustomerRepository - so our caller can use repo.List("abc","def") without having to specify the paging.
Finally - without LINQ, using pipes and filters becomes a lot more painful. You'll be writing some kind of text based query (TSQL, ESQL, HQL). You can obviously append strings, but it isn't very "pipe/filter"-ish. The "Criteria API" is a bit better - but not as elegant as LINQ.

When working with domain models and POCO classes, where do queries go?

I am new to domain models, POCO and DDD, so I am still trying to get my head around a few ideas.
One of the things I could not figure out yet is how to keep my domain models simple and storage-agnostic but still capable of performing some queries over its data in a rich way.
For instance, suppose that I have an entity Order that has a collection of OrdemItems. I want to get the cheapest order item, for whatever reason, or maybe a list of order items that are not currently in stock. What I don't want to do is to retrieve all order items from storage and filter later (too expensive) so I want to end up having a db query of the type "SELECT .. WHERE ITEM.INSTOCK=FALSE" somehow. I don't want to have that SQL query in my entity, or any variation of if that would tie me into a specific platform, like NHibernate queries on Linq2SQL. What is the common solution in that case?
Entities are the "units" of a domain. Repositories and services reference them, not vice versa. Think about it this way: do you carry the DMV in your pocket?
OrderItem is not an aggregate root; it should not be accessible through a repository. Its identity is local to an Order, meaning an Order will always be in scope when talking about OrderItems.
The difficulty of finding a home for the queries leads me to think of services. In this case, they would represent something about an Order that is hard for an Order itself to know.
Declare the intent in the domain project:
public interface ICheapestItemService
{
OrderItem GetCheapestItem(Order order);
}
public interface IInventoryService
{
IEnumerable<OrderItem> GetOutOfStockItems(Order order);
}
Declare the implementation in the data project:
public class CheapestItemService : ICheapestItemService
{
private IQueryable<OrderItem> _orderItems;
public CheapestItemService(IQueryable<OrderItem> orderItems)
{
_orderItems = orderItems;
}
public OrderItem GetCheapestItem(Order order)
{
var itemsByPrice =
from item in _orderItems
where item.Order == order
orderby item.Price
select item;
return itemsByPrice.FirstOrDefault();
}
}
public class InventoryService : IInventoryService
{
private IQueryable<OrderItem> _orderItems;
public InventoryService(IQueryable<OrderItem> orderItems)
{
_orderItems = orderItems;
}
public IEnumerable<OrderItem> GetOutOfStockItems(Order order)
{
return _orderItems.Where(item => item.Order == order && !item.InStock);
}
}
This example works with any LINQ provider. Alternatively, the data project could use NHibernate's ISession and ICriteria to do the dirty work.
Domain objects should be independent of storage, you should use the Repostiory pattern, or DAO to persist the objects. That way you are enforcing separation of concerns, the object itself should not know about how it is stored.
Ideally, it would be a good idea to put query construction inside of the repository, though I would use an ORM inside there.
Here's Martin Fowler's definition of the Repository Pattern.
As I understand this style of design, you would encapsulate the query in a method of an OrderItemRepository (or perhaps more suitably OrderRepository) object, whose responsibility is to talk to the DB on one side, and return OrderItem objects on the other side. The Repository hides details of the DB from consumers of OrderItem instances.
I would argue that it doesn't make sense to talk about "an Order that contains only the OrderItems that are not in stock". An "Order" (I presume) represents the complete list of whatever the client ordered; if you're filtering that list you're no longer dealing with an Order per se, you're dealing with a filtered list of OrderItems.
I think the question becomes whether you really want to treat Orders as an Aggregate Root, or whether you want to be able to pull arbitrary lists of OrderItems out of your data access layer as well.
You've said filtering items after they've come back from the database would be too expensive, but unless you're averaging hundreds or thousands of OrderItems for each order (or there's something else especially intensive about dealing with lots of OrderItems) you may be trying to optimize prematurely and making things more difficult than they need to be. I think if you can leave Order as the aggregate root and filter in your domain logic, your model will be cleaner to work with.
If that's genuinely not the case and you need to filter in the database, then you may want to consider having a separate OrderItem repository that would provide queries like "give me all of the OrderItems for this Order that are not in stock". You would then return those as an IList<OrderItem> (or IEnumerable<OrderItem>), since they're not a full Order, but rather some filtered collection of OrderItems.
In the service layer.

Domain Driven Design (Linq to SQL) - How do you delete parts of an aggregate?

I seem to have gotten myself into a bit of a confusion of this whole DDD\LinqToSql business. I am building a system using POCOS and linq to sql and I have repositories for the aggregate roots.
So, for example if you had the classes Order->OrderLine you have a repository for Order but not OrderLine as Order is the root of the aggregate. The repository has the delete method for deleting the Order, but how do you delete OrderLines?
You would have thought you had a method on Order called RemoveOrderLine which removed the line from the OrderLines collection but it also needs to delete the OrderLine from the underlying l2s table. As there isnt a repository for OrderLine how are you supposed to do it?
Perhaps have specialized public repostories for querying the roots and internal generic repositories that the domain objects actually use to delete stuff within the aggregates?
public class OrderRepository : Repository<Order> {
public Order GetOrderByWhatever();
}
public class Order {
public List<OrderLines> Lines {get; set;} //Will return a readonly list
public RemoveLine(OrderLine line) {
Lines.Remove(line);
//************* NOW WHAT? *************//
//(new Repository<OrderLine>(uow)).Delete(line) Perhaps??
// But now we have to pass in the UOW and object is not persistent ignorant. AAGH!
}
}
I would love to know what other people have done as I cant be the only one struggling with this.... I hope.... Thanks
You call the RemoveOrderLine on the Order which call the related logic. This does not include doing changes on the persisted version of it.
Later on you call a Save/Update method on the repository, that receives the modified order. The specific challenge becomes in knowing what has changed in the domain object, which there are several options (I am sure there are more than the ones I list):
Have the domain object keep track of the changes, which would include keeping track that x needs to be deleted from the order lines. Something similar to the entity tracking might be factored out as well.
Load the persisted version. Have code in the repository that recognizes the differences between the persisted version and the in-memory version, and run the changes.
Load the persisted version. Have code in the root aggregate, that gets you the differences given an original root aggregate.
First, you should be exposing Interfaces to obtain references to your Aggregate Root (i.e. Order()). Use the Factory pattern to new-up a new instance of the Aggregate Root (i.e. Order()).
With that said, the methods on your Aggregate Root contros access to its related objects - not itself. Also, never expose a complex types as public on the aggregate roots (i.e. the Lines() IList collection you stated in the example). This violates the law of decremeter (sp ck), that says you cannot "Dot Walk" your way to methods, such as Order.Lines.Add().
And also, you violate the rule that allows the client to access a reference to an internal object on an Aggregate Root. Aggregate roots can return a reference of an internal object. As long as, the external client is not allowed to hold a reference to that object. I.e., your "OrderLine" you pass into the RemoveLine(). You cannot allow the external client to control the internal state of your model (i.e. Order() and its OrderLines()). Therefore, you should expect the OrderLine to be a new instance to act upon accordingly.
public interface IOrderRepository
{
Order GetOrderByWhatever();
}
internal interface IOrderLineRepository
{
OrderLines GetOrderLines();
void RemoveOrderLine(OrderLine line);
}
public class Order
{
private IOrderRepository orderRepository;
private IOrderLineRepository orderLineRepository;
internal Order()
{
// constructors should be not be exposed in your model.
// Use the Factory method to construct your complex Aggregate
// Roots. And/or use a container factory, like Castle Windsor
orderRepository =
ComponentFactory.GetInstanceOf<IOrderRepository>();
orderLineRepository =
ComponentFactory.GetInstanceOf<IOrderLineRepository>();
}
// you are allowed to expose this Lines property within your domain.
internal IList<OrderLines> Lines { get; set; }
public RemoveOrderLine(OrderLine line)
{
if (this.Lines.Exists(line))
{
orderLineRepository.RemoveOrderLine(line);
}
}
}
Don't forget your factory for creating new instances of the Order():
public class OrderFactory
{
public Order CreateComponent(Type type)
{
// Create your new Order.Lines() here, if need be.
// Then, create an instance of your Order() type.
}
}
Your external client does have the right to access the IOrderLinesRepository directly, via the interface to obtain a reference of a value object within your Aggregate Root. But, I try to block that by forcing my references all off of the Aggregate Root's methods. So, you could mark the IOrderLineRepository above as internal so it is not exposed.
I actually group all of my Aggregate Root creations into multiple Factories. I did not like the approach of, "Some aggregate roots will have factories for complex types, others will not". Much easier to have the same logic followed throughout the domain modeling. "Oh, so Sales() is an aggregate root like Order(). There must be a factory for it too."
One final note is that if have a combination, i.e. SalesOrder(), that uses two models of Sales() and Order(), you would use a Service to create and act on that instance of SalesOrder() as neither the Sales() or Order() Aggregate Roots, nor their repositories or factories, own control over the SalesOrder() entity.
I highly, highly recommend this free book by Abel Avram and Floyd Marinescu on Domain Drive Design (DDD) as it directly answers your questions, in a shrot 100 page large print. Along with how to more decouple your domain entities into modules and such.
Edit: added more code
After struggling with this exact issue, I've found the solution. After looking at what the designer generates with l2sl, I realized that the solution is in the two-way associations between order and orderline. An order has many orderlines and an orderline has a single order. The solution is to use two way associations and a mapping attribute called DeleteOnNull(which you can google for complete info). The final thing I was missing was that your entity class needs to register for Add and Remove events from the l2s entityset. In these handlers, you have to set the Order association on the order line to be null. You can see an example of this if you look at some code that the l2s designer generates.
I know this is a frustrating one, but after days of struggling with it, I've got it working.
As a follow up....
I have switched to using nhibernate (rather than link to sql) but in effect you dont need the repos for the OrderLine. If you just remove the OrderLine from the collection in Order it will just delete the OrderLine from the database (assuming you have done your mapping correctly).
As I am swapping out with in-memory repositories, if you want to search for a particular order line (without knowing the order parent) you can write a linq to nhibernate query that links order to orderline where orderlineid = the value. That way it works when querying from the db and from in memory. Well there you go...