+1  A: 

You are fighting the system... 2 thoughts:

  • if you know you need the other data (nested foreach), why wouldn't you want to use LoadWith? That is pretty-much the text-book use case
  • since you (from post) know that object tracking is required for lazy loading, why not just enable object tracking; data-contexts should usually be considered "units of work" (i.e. short-lived), so this isn't likely to hurt much in reality.

See the official replies here for why these two options (object tracking and deferred loading) are linked.

Marc Gravell
The code you see is a much simplified version of my real code. My code first assumed LoadWith, now I'm trying to optimize and lazy load instead of eager load (because of performance), so just before I really need the data I want want to load it. It may really leave the scope of the datacontext...
ArielBH
and data will be passed through the application.
ArielBH
Are you actually suer, from profiling, that ObjectTracking is causing you a problem. Given your requirements, I'd just enable it. Personally, though, I like a repository pattern with no lazy loading - my repository fetches data (or updates data) within a method and then has nothing to do with it...
Marc Gravell
The problem is that if I've got plenty of relations (I've ended with 17 LoadWith<> statements) loading a single entity can take much time. what should I do?
ArielBH
BTW about repository pattern. Do you consider this article as valid guide for implementing with Linq2Sql ? http://www.codeproject.com/KB/architecture/linqrepository.aspx
ArielBH
I'd argue that needing 17 sets of external data means that you aren't doing controlled data access - i.e. methods that do 1 clear thing. My thoughts are: http://marcgravell.blogspot.com/2009/02/pragmatic-linq.html
Marc Gravell
Re that article - I lean away from returning IEnumerable<T>/IQueryable<T> from repo methods, as it means you can't unit/integration test it properly. If I call a DAL method, I want it to do its job and step away... YMMV, however.
Marc Gravell
Read you blog post, it sounds reasonable to me.It is possible for you to publish a small example of how to structure it correctly? I would eternally grateful:)
ArielBH
I'm not sure I can do that today - but essentially my repository methods return homogeneous data (or very tightly coupled data such as header/line) *only*. No IEnumerable<T>/IQueryable<T>/Expression<T> on the interface, and no lazy loading. The navigation properties are internal, so usable at the
Marc Gravell
repository, but not by the caller - allows you to write interesting queries while retaining purity of the methods. Spanning queries (search etc) return a bespoke "FooResult" type (list/array-of) rather than trying to return the regular entities.
Marc Gravell
For all I know I'm going crazy/er/ but it seems to work pretty well. The repository is then a black box, and can be tested and mocked very robustly. Lazy loading etc doesn't allow this.
Marc Gravell
What do you think on that approach? class Repository<T> where T : class { public List<T> Find(Func<T, bool> expr) { using (context = new TestDbDataContext() { context.ObjectTrackingEnabled = false; return context.GetTable<T>().Where(expr).ToList(); }}}
ArielBH
Did I got your meaning correctly?
ArielBH
You'll need Expression<Func<T,bool>> (not just Func<T,bool>) to get that to work - which means that your repository is not at the mercy of the caller; you a: can't prove the expression is usable (not all operations are mapped), and b: can't profile/optimise it. Which is why *personally* I prefer ...
Marc Gravell
... a closed repository - i.e. my Find method might have discreet arguments for common search patterns, but that is defined by the interface. It also means that the repository is not LINQ-specific, so you can still provide any implementation under the hood. This view comes, in part, from having ...
Marc Gravell
... to support apps that tend to live for a while, with re-use. If you are writing a standalone, specific app, then use whatever works.
Marc Gravell
If an entity is very different from it counterparts than you will end up writing a different repository for each entity. Right ?
ArielBH
Well, I wouldn't have a Repository<T>, if that is what you mean... a single repository interface might support a few closely related entities. A single repository class *could* implement multiple repository interfaces (although whether it *should* is another theme). It comes down to "aggregates".
Marc Gravell
I like repositories returning IQueryable as query can be further adjusted along the way (specification pattern etc.)The repository's purpose is to wrap data storage semantics (linq2sql or whatever else you're using) to aggregate entities defined in the code.
Eran Kampf
@Eran - while useful, it makes it impossible to test caller and callee in isolation, and impossible to profile / optimize.
Marc Gravell
Eran Kampf
Because you need to factor in the translation to the backend storage model. Not all expressions can be translated to TSQL/ESQL/HQL (depending on the API) - indeed, something as simple as Single() works differently between EF and LINQ-to-SQL. Unit tests would typically use LINQ-to-Objects, but that..
Marc Gravell
..means nothing if your actual repository has to talk to a database or external resource. Hence you cannot do unit testing (or rather: it is meaningless). If you expose IQueryable<T> or Expression on the repository API, *only* full integration tests are valid.
Marc Gravell
I see your point... Its certainly a design consideration. I built a Services layer on top of the repositories that are in charge of all the interaction with the repositories (program works against the services and not directly with repositories). The services is where unit testing is important...
Eran Kampf
Marc, I've just stumbled on Ayende's post on repository what do you think in correspondence to your own post.http://ayende.com/Blog/archive/2009/04/17/repository-is-the-new-singleton.aspx
ArielBH
@ArielBH - I agree with some of the issues raised, but **especially** with the current state of LINQ-to-SQL vs EF, I genuinely like the abstraction offered, and the mock aspects. As always, the needs of specific projects will be important, but for now at least, abstraction behind an interface is my preferred route. Not *at least* until 4.0 (maybe one of the service packs), but *at some point* I'd like to have the option to switch to EF without a complete rewrite of my higher layers.
Marc Gravell
A: 

Use a LazyList: http://blog.wekeroad.com/blog/lazy-loading-with-the-lazylist/

Eran Kampf
Yeah, I know about that one. But this one demands major rewrites of the generated entities and queries.
ArielBH
From experience, having your own data model beats counting on Linq2Sql... (too many advantages to list here)
Eran Kampf
Worth thought but irrelevant.
ArielBH
Thats the right way to do what you want
Eran Kampf
Havent played much with the Linq2Sql autogenerated class but maybe you can get it to NOT generate the Gifts property and then add a partial class to Employee and define that property yourself (using IQueryable rather than EntitySet or whatever Linq2Sql uses)
Eran Kampf