﻿<?xml version="1.0" encoding="utf-8"?><rss version="2.0"><channel><title>Ayende @ Rahien</title><link>http://ayende.com</link><description>Ayende @ Rahien</description><copyright>Copyright (C) Ayende Rahien  2004 - 2021 (c) 2026</copyright><ttl>60</ttl><item><title>Dennis Doomen commented on Ask Ayende: Life without repositories, are they worth living?</title><description>I myself am slowly moving away from the more traditional repository patterns and adapting more and more aspects of CQRS. Two important articles that have been the driving force behind that are these:

"Meanwhile… on the command side of my architecture"
http://www.cuttingedge.it/blogs/steven/pivot/entry.php?id=91

"Meanwhile… on the query side of my architecture"
http://www.cuttingedge.it/blogs/steven/pivot/entry.php?id=92

We've applied both in a large enterprise-class system and they've proven to make our life a lot easier. We've applied TDD all the way and usually use SqlLIte to make sure our optimized queries still work when using NH's new QueryOver API.</description><link>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment53</link><guid>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment53</guid><pubDate>Fri, 20 Jan 2012 14:48:30 GMT</pubDate></item><item><title>Matt commented on Ask Ayende: Life without repositories, are they worth living?</title><description>Thanks, I had always assumed that was the case, and have wrapped transactions where I've needed them.  I really like Josh's idea in the MVC world of using an attribute for that purpose.

I have to admit, with NHibernate I am seeing your point and I think a half-way approach is probably best.  For complex queries that are useful in a shared context I'm still for moving it into a service layer of some sort.  Update commands - service layer.

However, for simple queries, I have to concede there is no point in adding it to the repository - it serves little to no purpose.  Pragmatism and applying the principle of DRY.</description><link>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment52</link><guid>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment52</guid><pubDate>Fri, 20 Jan 2012 13:31:58 GMT</pubDate></item><item><title>Ayende Rahien commented on Ask Ayende: Life without repositories, are they worth living?</title><description>wrongwrong,
You are so articulate, you convinced me.</description><link>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment51</link><guid>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment51</guid><pubDate>Fri, 20 Jan 2012 12:57:14 GMT</pubDate></item><item><title>Ayende Rahien commented on Ask Ayende: Life without repositories, are they worth living?</title><description>Mark,
I have done a review about S#arp (look at the reviews tag)
And I have a review about S#arp Life that is supposed to be published in a few weeks</description><link>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment50</link><guid>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment50</guid><pubDate>Fri, 20 Jan 2012 12:56:55 GMT</pubDate></item><item><title>Ayende Rahien commented on Ask Ayende: Life without repositories, are they worth living?</title><description>Marco,
Caching is not a cross cutting concern.
I am afraid that I don't understand your question</description><link>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment49</link><guid>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment49</guid><pubDate>Fri, 20 Jan 2012 12:55:58 GMT</pubDate></item><item><title>Ayende Rahien commented on Ask Ayende: Life without repositories, are they worth living?</title><description>Joseph,
Why would they share the same data layer? They have drastically different needs.
They might (or might not) share the same database, but that is beside the point.</description><link>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment48</link><guid>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment48</guid><pubDate>Fri, 20 Jan 2012 12:54:04 GMT</pubDate></item><item><title>Ayende Rahien commented on Ask Ayende: Life without repositories, are they worth living?</title><description>Matt,
There is a cost for doing BeginTransaction (you have to go to the DB for it).
But you can do that lazily (on first session access, frex).
That is the power of abstracting away the infrastructure.</description><link>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment47</link><guid>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment47</guid><pubDate>Fri, 20 Jan 2012 12:53:09 GMT</pubDate></item><item><title>Ayende Rahien commented on Ask Ayende: Life without repositories, are they worth living?</title><description>JamesG,
A controller's action is subject to SRP as well, most of the time, when I am putting a lot in the action, that is because it is doing a read, and that is the best place to put it.
All of those thins that you mentioned are logic, and that happen on write actions. I have very little problem with putting them behind a service boundary.</description><link>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment46</link><guid>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment46</guid><pubDate>Fri, 20 Jan 2012 12:52:05 GMT</pubDate></item><item><title>Frank commented on Ask Ayende: Life without repositories, are they worth living?</title><description>@Wyatt Barnett, what data access code is in the controlers? The ORM is the actual data acess layer. Your controller is telling it what to fetch.

In my experience, when people abstract the ORM behind some construct, you'll see stuff like a Search or Filter method where you pass in some abstractions to define the filter to use. So why not just use the ORM constructs (especially since most ORMs support LINQ)?

</description><link>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment45</link><guid>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment45</guid><pubDate>Thu, 19 Jan 2012 22:42:08 GMT</pubDate></item><item><title>wrongwrong commented on Ask Ayende: Life without repositories, are they worth living?</title><description>Ayende is definitely wrong on this topic</description><link>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment44</link><guid>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment44</guid><pubDate>Thu, 19 Jan 2012 22:27:29 GMT</pubDate></item><item><title>Mark commented on Ask Ayende: Life without repositories, are they worth living?</title><description>Ayende what are your thoughts about using S#arp Architecture and its built in repositories?  I've found this framework to be really nice for larger more complex applications coded with MVC.</description><link>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment43</link><guid>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment43</guid><pubDate>Thu, 19 Jan 2012 19:51:46 GMT</pubDate></item><item><title>Stan Kazakh commented on Ask Ayende: Life without repositories, are they worth living?</title><description>Ayende had a series of posts titled "Refactoring toward frictionless &amp; odorless code" that covered how you could wire up NHibernate transactions into your infrastructure, meaning your MVC controllers didn't have to worry about this - see http://ayende.com/blog/4803/refactoring-toward-frictionless-odorless-code-the-baseline for the first one.</description><link>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment42</link><guid>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment42</guid><pubDate>Thu, 19 Jan 2012 19:36:28 GMT</pubDate></item><item><title>Josh commented on Ask Ayende: Life without repositories, are they worth living?</title><description>@John I've found using Ninject.Web.Mvc the easiest way to handle sessions. http://pastebin.com/uiwdNKY8</description><link>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment41</link><guid>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment41</guid><pubDate>Thu, 19 Jan 2012 18:27:14 GMT</pubDate></item><item><title>Marco commented on Ask Ayende: Life without repositories, are they worth living?</title><description>i'm also talking about caching data, not the results the view displays.
</description><link>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment40</link><guid>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment40</guid><pubDate>Thu, 19 Jan 2012 17:43:33 GMT</pubDate></item><item><title>Marco commented on Ask Ayende: Life without repositories, are they worth living?</title><description>so how are you recommending caching when making calls directly from the controllers? i would not think extension methods as those are "nice to have" and do not force the client using the ISession/IDbContext.</description><link>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment39</link><guid>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment39</guid><pubDate>Thu, 19 Jan 2012 17:42:21 GMT</pubDate></item><item><title>Josh commented on Ask Ayende: Life without repositories, are they worth living?</title><description>@John That is a lot of code... Also, I don't see a way to set the transactions isolation level when doing it in an HttpModule like that.</description><link>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment38</link><guid>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment38</guid><pubDate>Thu, 19 Jan 2012 17:39:49 GMT</pubDate></item><item><title>Joseph Daigle commented on Ask Ayende: Life without repositories, are they worth living?</title><description>It all really just depends on how much complexity the system actually needs.

If you're just building a single web-app that talks to a single data-source, then you certainly don't need multiple levels of abstraction. You can get away with writing your data access logic against your ORM in an MVC controller because each unit of code/logic is likely to only ever exist in that one place, and thus be tested.

If you're building a larger-scale, maybe an "enterprise" level system, with multiple application-layer components, then abstracting these gritty details into a "service" layer with some well-designed API might be the pragmatic way to go.</description><link>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment37</link><guid>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment37</guid><pubDate>Thu, 19 Jan 2012 16:28:47 GMT</pubDate></item><item><title>Josh Schwartzberg commented on Ask Ayende: Life without repositories, are they worth living?</title><description>I also like adding helpers that only extract away the resource management and not further abstracting the nhibernate API like so:

public void ExecuteAndCommit(Action&lt;Session&gt; actionOnSession){
   using(var session = _sessionFactory.OpenSession()) { 
   using(var transaction = session.BeginTransaction()) {
      actionOnSession(session);
   }
   }
}

and using it like:

var task = new Task();
_dbExecutor.ExecuteAndCommit((s) =&gt; s.Save(task));</description><link>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment36</link><guid>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment36</guid><pubDate>Thu, 19 Jan 2012 15:57:13 GMT</pubDate></item><item><title>Stefan commented on Ask Ayende: Life without repositories, are they worth living?</title><description>@Matt, personally I abstract away complex scenarios when needed. Those are usually quite rare compared to the number of simple queries (in my own experience). Depends on the application/context.</description><link>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment35</link><guid>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment35</guid><pubDate>Thu, 19 Jan 2012 15:27:58 GMT</pubDate></item><item><title>John commented on Ask Ayende: Life without repositories, are they worth living?</title><description>Talking of handling sessions what do you think of this?

http://nhforge.org/blogs/nhibernate/archive/2011/03/03/effective-nhibernate-session-management-for-web-apps.aspx</description><link>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment34</link><guid>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment34</guid><pubDate>Thu, 19 Jan 2012 14:51:11 GMT</pubDate></item><item><title>Wyatt Barnett commented on Ask Ayende: Life without repositories, are they worth living?</title><description>What about settling in the middle a bit -- I totally agree that the amount of ceremony in the "best practices examples" is absolutely overblown. But I think having direct data access inside your UI layer is a pretty bad choice as well -- even if the modern UI layer is a bit more testable and fungable than the UI layers of years past. I also think having an implied transaction around every HTTP request is perhaps overkill, especially with everything hitting the managed pipeline. Which is a really long-winded way of saying "what about our good buddy the service layer? He can handle the complex cases rather transparently, access other services and should be allowed to access data directly. We can have explicit save methods for those of us that like those things. And I don't feel like a dirty little ****** by talking to the session in MVC action methods."</description><link>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment33</link><guid>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment33</guid><pubDate>Thu, 19 Jan 2012 14:36:43 GMT</pubDate></item><item><title>Matt commented on Ask Ayende: Life without repositories, are they worth living?</title><description>@Josh - nice idea - never thought of doing that but it makes perfect sense.  Thanks for the tip.

@Stefan and @Alexander - I take your point and yes it does look like it covers most scenarios, the query is just an example.  What about queries that require snapshot data i.e. a combination of a number of tables for a report?</description><link>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment32</link><guid>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment32</guid><pubDate>Thu, 19 Jan 2012 14:32:24 GMT</pubDate></item><item><title>Roland commented on Ask Ayende: Life without repositories, are they worth living?</title><description>In unittests, whats different between

var filteredProducts = Testsession.Query.WhereProductsOnSale().ToList();
Asser.Equal(2, filteredProducts.Count);


var filteredProducts = ProductsRepository.GetProductsOnSale().ToList();
Asser.Equal(2, filteredProducts.Count);</description><link>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment31</link><guid>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment31</guid><pubDate>Thu, 19 Jan 2012 14:18:18 GMT</pubDate></item><item><title>Stefan commented on Ask Ayende: Life without repositories, are they worth living?</title><description>Matt, your query could be written like this:

var customer = Session.Query&lt;Customer&gt;()
	.Where(x =&gt; x.Email == email)
	.FirstOrDefault();

And in a view you might need to display some customer settings as well.
var customer = Session.Query&lt;Customer&gt;()
	.Where(x =&gt; x.Email == email)
	.Fetch(x =&gt; x.Settings)
	.FirstOrDefault();</description><link>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment30</link><guid>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment30</guid><pubDate>Thu, 19 Jan 2012 14:04:44 GMT</pubDate></item><item><title>Josh commented on Ask Ayende: Life without repositories, are they worth living?</title><description>@Matt You can create an action filter for doing the transactions and place them where ever you need them. You can also specify the isolation level that way.</description><link>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment29</link><guid>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment29</guid><pubDate>Thu, 19 Jan 2012 13:56:50 GMT</pubDate></item><item><title>Alexander Nyquist commented on Ask Ayende: Life without repositories, are they worth living?</title><description>Matt,

That's easily done using extension methods. Clean, simple and reusable.

public static IEnumerable&lt;T&gt; GetAll&lt;T&gt;(this ISession instance, Expression&lt;Func&lt;T, bool&gt;&gt; where) where T : class {
            return instance.QueryOver&lt;T&gt;().Where(where).List();
}

var customers = Current.Session.GetAll&lt;Customer&gt;(x =&gt; x.Email == "foo@bar");</description><link>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment28</link><guid>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment28</guid><pubDate>Thu, 19 Jan 2012 13:51:28 GMT</pubDate></item><item><title>Marco commented on Ask Ayende: Life without repositories, are they worth living?</title><description>IMO the core of the problem stems from using one model for both writes and reads. for my write side, each use case sits behind an role interface who is responsible for fetching (including eager) and whatever else needs to be performed and simply handing back a ref to the interface. so now my application layer (client) only knows about a particular behavior abstraction and nothing else.



</description><link>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment27</link><guid>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment27</guid><pubDate>Thu, 19 Jan 2012 13:46:29 GMT</pubDate></item><item><title>Matt commented on Ask Ayende: Life without repositories, are they worth living?</title><description>That was with entity framework.  NHibernate is different.  You could put a static method on Customer, of course, but that has unit test implications.

</description><link>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment26</link><guid>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment26</guid><pubDate>Thu, 19 Jan 2012 13:32:59 GMT</pubDate></item><item><title>Matt commented on Ask Ayende: Life without repositories, are they worth living?</title><description>Ugh, apologies for the terrible formatting there.</description><link>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment25</link><guid>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment25</guid><pubDate>Thu, 19 Jan 2012 13:31:19 GMT</pubDate></item><item><title>Wayne M commented on Ask Ayende: Life without repositories, are they worth living?</title><description>I seem to recall Ayende saying that he would use some kind of extension method to handle an example like that, but I don't 100% remember.</description><link>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment24</link><guid>http://ayende.com/153701/ask-ayende-life-without-repositories-are-they-worth-living#comment24</guid><pubDate>Thu, 19 Jan 2012 13:30:52 GMT</pubDate></item></channel></rss>