For the most part, this is an excellent book and I recommend it to all .NET developers. I can't give the book 5 stars though for reasons I'll explain in a moment. But let me first mention the strong points of the book. The authors clearly know what they're talking about and their command of the subject matter is pretty much beyond question. They also present most of the available options fairly, unlike other books based on OO. Most books based on OO architectures pretend that heavy, complex OO solutions are appropriate in (most) all situations. The authors clearly recognize that high-performance database-centric code still has an appropriate place in many, if not most, situations. This advice is not only right on, but it gives the authors credibility, which is lacking in many other OO authors, who, again, promote piggy solutions to relatively simple problems (and by simple, I'm still talking about 95% of software problems) better handled by more efficient, high-performance, database-centric code.
Now where I disagree with the authors is primarily around the "domain model" architecture. Probably my biggest point of contention is the idea that you can design your domain irrespective of the database design. That is, you design the domain and then "generate" the database based on this design. Historically, this approach would be considered backwards compared to what has traditionally been done in software design, and in my view, it is a recipe for disaster. Designing the object model first and essentially leaving the database largely to chance, ends up resulting in a bunch of convoluted mapping classes or files that nobody understands except for the geek who created them. And, to put it mildly, these mapping strategies don't work well at all; resulting in massive maintenance and extensibility problems. The DBA (or someone who understands how to design a high-performance database) should be intimately involved at the beginning of just about every project. This is particularly true since the database will often serve multiple masters, not just the enterprise app that it was initially created to support. So, if the database is designed poorly (by allowing a domain design to dictate its structure), you're generally going to be hosed if you try to use it for something else.
I also agree substantially with Jeff Roughgarden's review. I think Jeff hits the nail on the head when he says:
"This book is a classic example of the distrust that application developers (i.e. C# guys) have of database developers (i.e. SQL guys). Many application developers know C# really well (e.g. love expounding on the beauties of generics, lambda expressions, and dynamic binding) but for some reason won't learn SQL and relational databases, despite knowing their data will eventually wind up in one. So they flock to use object/relational mapping tools and things like LINQ to avoid learning SQL. These tools generate dynamic SQL code that generally performs quite poorly. But no matter, the authors say 'An O/RM tool shields you entirely from the details of the DBMS query language.' As if that is desirable. I say 'Suck it up, C# guys, and learn how to write good SQL."
I couldn't agree more. In fact, in the past I've hired some C# "middleware" guys and they were absolutely dreadful. They can write textbook OO code, but it's so piggy, bloated, and slow that it's completely unuseable. These guys have no concept of high-peformance code and they're too lazy (or delusional) to spend the time learning high-performance T-SQL. They also just don't appreciate that performance is almost entirely in the database and that the database is the most challenging component to scale out. So, it's essential that the database is designed correctly and has sufficient priority.
It's true, as Dino points out, that putting business logic in sps is generally a bad thing, but even worse is using piggy ORM code that spews absolutely dreadful T-SQL. On a related note, Dino makes much of the comparison between inline SQL and sps, arguing that sps don't buy you much. The problem is that this is the wrong comparison! The relevant comparison is between optimized sps and the god-awful SQL produced by ORM. Sps will always outperform ORM, and often by a large margin. Finally, the authors don't even discuss the peformance implications of ORM. This is a massive omission. As a wounded veteran of NHibernate, I can say (with the scars to prove it) that ORM performs horrendously compared to high-peformance data layers based on optimized SQL, indexes, and oversight by a DBA.
Finally, you've probably noticed that I have a bias towards high-performance code. You can obviously contrast that with the bias of the authors who don't put much of a premium on performance. The authors note for example that premature optimization is this great evil. While that point has some merit, I completely disagree that performance should be a minor consideration of an architect. If you don't consider it, then one day, a few of your customers start complaining, and then a few more do. At this point, you can usually make some improvements, but they often involve hacking up your code, bypassing your ORM code with better performing code, etc. You often end with a cluster. You're much better off keeping performance in mind at all stages of the project. See Richard Kiessig's book on ASP.NET for a similar view of where performance should fit in your thinking.