Ok, those are old news, but it appears that I’m not able to learn from other people’s mistakes.
1. Leaky abstractions make you look stupid. If you are heavily using of EF's lazy loading, don't pretend that you'll be able to abstract EF away.
2. Every abstraction should solve some problem (current or foreseeable). Be able to envision use cases for every extension point you created.
3. Queries should be made in the simplest way possible. Use plain SQL, Document DBs, XML, whatever. No need for your fancy Repository pattern here.
4. Validation is about ensuring that input is plausible. It is performed with no context in mind by the Command object (or something similar) itself. Decision about whether this input will actually hit database is made a) after all preliminary checks have passed and b) after verifying the input against the most up-to-date data with the most restrictive transaction isolation level possible (think singleton double-checking)
5. The data you are showing on UI is already stale. Other users have already updated the storage. Don't freak out about this. Allow inconsistencies. Know the minimum time that's required for changes to actually appear on UI. Approach this time by scaling-out reads.
6. CQRS examples are everywhere: RavenDB with it's background indexes calculation, OLAP solutions with their data marts, etc.
7. Scale-in is a perfectly valid option for the transactional storage that you'll use for writing.
8. DDD is mostly a way you communicate with product owner.
I totally recommend CQRS introduction by Udi Dahan – this is a real eye-opener.