Skip to content

Instantly share code, notes, and snippets.

@PaulStovell
Created January 4, 2012 11:44
Show Gist options
  • Save PaulStovell/1559702 to your computer and use it in GitHub Desktop.
Save PaulStovell/1559702 to your computer and use it in GitHub Desktop.
Ayende RSS as at 4 Jan 2012 11:44 AM GMT
<?xml version="1.0" encoding="utf-8"?><rss version="2.0"><channel><title>Ayende @ Rahien</title><link>http://ayende.com/blog/syndication/rss</link><description>Ayende @ Rahien</description><copyright>Copyright (C) Ayende Rahien 2004 - 2011 (c) 2012</copyright><ttl>60</ttl><item><title>Out of context, architecture is nothing but modern art</title><description>&lt;p&gt;
When I am thinking about modern art, I am thinking about an experience that I had that was remarkably similar to &lt;a href="http://tonyvanhelsing.blogspot.com/2011/05/modern-art.html"&gt;this one&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;
&lt;img src="http://1.bp.blogspot.com/-e2aJXImlhfY/TcKrSw69D4I/AAAAAAAAAIU/xjjNNNGj_Fw/s1600/modern_art.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;
I got a lot of comments regarding &lt;a href="http://ayende.com/blog/152706/application-review-northwind-starter-kit"&gt;my review&lt;/a&gt; of the &lt;a href="http://nsk.codeplex.com/"&gt;Northwind Starter Kit project&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;
Here is the deal, if you want to demonstrate complex ways to solve a problem, you had better make sure that you are actually solving a problem that requires a complex solution. If you are demonstrating how to solve a simple problem in a complex way, you are basically doing disservice to the reader.&lt;/p&gt;
&lt;p&gt;
When I wanted to write a sample app to demonstrate something, I either chose to demonstrate the actual technology (writing a ToDo app) or I spent dozens of posts establishing the context (yes, that is Macto, I&amp;rsquo;ll get back to it).&lt;/p&gt;
&lt;p&gt;
But since so many people seems to have been offended by my slight of dismissing the project based on what seemed like just the number of projects, I&amp;rsquo;ll do a full review series on that. My point was to make it clear that creating complex solutions for simple problems is &lt;strong&gt;wrong&lt;/strong&gt;, especially if you are trying to demonstrate a real workable system. Without the proper context, all of this stuff is just cargo cult.&lt;/p&gt;
</description><link>http://ayende.com/blog/153027/out-of-context-architecture-is-nothing-but-modern-art</link><guid>http://ayende.com/blog/153027/out-of-context-architecture-is-nothing-but-modern-art</guid><pubDate>Wed, 04 Jan 2012 10:00:00 GMT</pubDate></item><item><title>Application review: Northwind Starter Kit</title><description>&lt;p&gt;I continue to try to find a sample application for Northwind to use as my contrasting example for an article that I am writing, and I found the &lt;a href="http://nsk.codeplex.com/"&gt;Northwind Starter Kit&lt;/a&gt; project. Even the project summary page gave me a few twitches, here is a small piece with the twitch inducing stuff bolded:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;The application has been designed using common &lt;strong&gt;patterns&lt;/strong&gt;, such as the ones defined within the "classic" "&lt;strong&gt;Designs Patterns&lt;/strong&gt;" by Erich Gamma et al. and "&lt;strong&gt;Pattern of Enterprise Application Architecture&lt;/strong&gt;", by Martin Fowler; though not required, these lectures are strongly recommended.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Guys! This is &lt;em&gt;Northwind&lt;/em&gt;, the likelihood that you’ll need design patterns to build this application is nil to none! That just screens complexity overload.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;Domain logic is implemented by means of a &lt;strong&gt;Domain Model&lt;/strong&gt;, onto a &lt;strong&gt;layer of services &lt;/strong&gt;adds &lt;strong&gt;application logic&lt;/strong&gt;. The model is persisted by a &lt;strong&gt;DAL &lt;/strong&gt;designed around the principles of the "&lt;strong&gt;Repository&lt;/strong&gt;" patterns, which has been implemented in a LINQ-friendly way.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Northwind is a CRUD app, at its core, all of those things are adding complexity, and they aren’t really adding much at all. In fact, they are going to create just noise, and make working with things that much harder.&lt;/p&gt; &lt;p&gt;And then I opened the project, and I got this:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Application-review-Northwind-Starter-Kit_B55D/image_2.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ayende.com/blog/Images/Windows-Live-Writer/Application-review-Northwind-Starter-Kit_B55D/image_thumb.png" width="478" height="638"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;I mean, &lt;em&gt;really&lt;/em&gt;? Seriously?!&amp;nbsp; 22(!) projects to do a sample application using Northwind?&lt;/p&gt; &lt;p&gt;This is the point where I gave up on this as something that could be useful, but here are a few other gems as well:&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Application-review-Northwind-Starter-Kit_B55D/image_4.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ayende.com/blog/Images/Windows-Live-Writer/Application-review-Northwind-Starter-Kit_B55D/image_thumb_1.png" width="637" height="225"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Application-review-Northwind-Starter-Kit_B55D/image_8.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ayende.com/blog/Images/Windows-Live-Writer/Application-review-Northwind-Starter-Kit_B55D/image_thumb_3.png" width="649" height="238"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;I really like how the Update method does what it is meant to do, right?&lt;/p&gt; &lt;p&gt;Note that in either implementation, we are looking at &lt;em&gt;totally and drastically &lt;/em&gt;different behavior. &lt;/p&gt; &lt;p&gt; Let us look at the interface, too:&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Application-review-Northwind-Starter-Kit_B55D/image_6.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ayende.com/blog/Images/Windows-Live-Writer/Application-review-Northwind-Starter-Kit_B55D/image_thumb_2.png" width="1102" height="374"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;The design is straight out of Patterns of Enterprise Application Architecture, and it is &lt;em&gt;totally the wrong design&lt;/em&gt; to be using if you are using a modern OR/M. &lt;/p&gt; &lt;p&gt;Seriously, this is Northwind we are talking about, why make things so freaking complex?!&lt;/p&gt;</description><link>http://ayende.com/blog/152706/application-review-northwind-starter-kit</link><guid>http://ayende.com/blog/152706/application-review-northwind-starter-kit</guid><pubDate>Tue, 03 Jan 2012 10:00:00 GMT</pubDate></item><item><title>Structuring your Unit Tests, why?</title><description>&lt;p&gt;I am a strong believer in automated &lt;strike&gt;unit &lt;/strike&gt;tests. And I read &lt;a href="http://haacked.com/archive/2012/01/02/structuring-unit-tests.aspx"&gt;this post by Phil Haack&lt;/a&gt; with part amusement and part wonder. &lt;/p&gt; &lt;p&gt;RavenDB currently has close to 1,400 tests in it. We routinely ask for failing tests from users and fix bugs by writing tests to verify fixes.&lt;/p&gt; &lt;p&gt;But structuring them in terms of source code? That seems to be very strange.&lt;/p&gt; &lt;p&gt;You can take a look at the source code layout of some of our tests here: &lt;a href="https://github.com/ayende/ravendb/tree/master/Raven.Tests/Bugs"&gt;https://github.com/ayende/ravendb/tree/master/Raven.Tests/Bugs&lt;/a&gt;&lt;/p&gt; &lt;p&gt;It is a dumping ground, basically, for tests. That is, for the most part, I view tests as very important in telling me “does this !@#! works or not?” and that is about it. Spending a lot of time organizing them seems to be something of little value from my perspective.&lt;/p&gt; &lt;p&gt;If I need to find a particular test, I have R# code browsing to help me, and if I need to find who is testing a piece of code, I can use Find References to get it.&lt;/p&gt; &lt;p&gt;At the end, it boils down to the fact that I don’t consider tests to be, by themselves, a value to the product. Their only value is their binary ability to tell me whatever the product is okay or not. Spending a lot of extra time on the tests distract from creating &lt;em&gt;real &lt;/em&gt;value, shippable software.&lt;/p&gt; &lt;p&gt;What I &lt;em&gt;do&lt;/em&gt; deeply care about with regards to structuring the tests is the actual structure of the &lt;em&gt;test&lt;/em&gt;. It is important to make sure that all the tests looks very much the same, because I should be able to look at any of them and figure out what is going on rapidly.&lt;/p&gt; &lt;p&gt;I am not going to use the RavenDB example, because that is system software and usually different from most business apps (although we use a similar approach there). Instead, here are a few tests from our new ordering system:&lt;/p&gt; &lt;blockquote&gt;&lt;pre class="csharpcode"&gt;[Fact]
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Will_send_email_after_trial_extension()
{
Consume&amp;lt;ExtendTrialLicenseConsumer, ExtendTrialLicense&amp;gt;(&lt;span class="kwrd"&gt;new&lt;/span&gt; ExtendTrialLicense
{
ProductId = &lt;span class="str"&gt;"products/nhprof"&lt;/span&gt;,
Days = 30,
Email = &lt;span class="str"&gt;"you@there.gov"&lt;/span&gt;,
});
var email = ConsumeSentMessage&amp;lt;NewTrial&amp;gt;();
Assert.Equal(&lt;span class="str"&gt;"you@there.gov"&lt;/span&gt;, email.Email);
}
[Fact]
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Trial_request_from_same_customer_sends_email()
{
Consume&amp;lt;NewTrialConsumer, NewTrial&amp;gt;(&lt;span class="kwrd"&gt;new&lt;/span&gt; NewTrial
{
ProductId = &lt;span class="str"&gt;"products/nhprof"&lt;/span&gt;,
Email = &lt;span class="str"&gt;"who@is.there"&lt;/span&gt;,
Company = &lt;span class="str"&gt;"h"&lt;/span&gt;,
FullName = &lt;span class="str"&gt;"a"&lt;/span&gt;,
TrackingId = Guid.NewGuid()
});
Trial firstTrial;
&lt;span class="kwrd"&gt;using&lt;/span&gt; (var session = documentStore.OpenSession())
{
firstTrial = session.Load&amp;lt;Trial&amp;gt;(1);
}
Assert.NotNull(ConsumeSentMessage&amp;lt;SendEmail&amp;gt;());
Consume&amp;lt;NewTrialConsumer, NewTrial&amp;gt;(&lt;span class="kwrd"&gt;new&lt;/span&gt; NewTrial
{
TrackingId = firstTrial.TrackingId,
Email = firstTrial.Email,
Profile = firstTrial.ProductId.Substring(&lt;span class="str"&gt;"products/"&lt;/span&gt;.Length)
});
var email = ConsumeSentMessage&amp;lt;SendEmail&amp;gt;();
Assert.Equal(&lt;span class="str"&gt;"Hibernating Rhinos - Trials Agent"&lt;/span&gt;, email.ReplyToDisplay);
}
&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/blockquote&gt;
&lt;p&gt;As you can probably see, we have a structured way to send input to the system, and we can verify the output and the side affects (creating the trial, for example).&lt;/p&gt;
&lt;p&gt;This leads to a system that can be easily tested, but doesn’t force us to spend too much time in the ceremony of tests.&lt;/p&gt;</description><link>http://ayende.com/blog/152897/structuring-your-unit-tests-why</link><guid>http://ayende.com/blog/152897/structuring-your-unit-tests-why</guid><pubDate>Mon, 02 Jan 2012 06:48:00 GMT</pubDate></item><item><title>Application analysis: Northwind.NET</title><description>&lt;p&gt;For an article I am writing, I wanted to compare a RavenDB model to a relational model, and I stumbled upon the following &lt;a href="http://northwind.codeplex.com/"&gt;Northwind.NET project&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;I plugged in the &lt;a href="http://efprof.com"&gt;Entity Framework Profiler&lt;/a&gt; and set out to watch what was going on. To be truthful, I expected it to be bad, but I honestly did &lt;em&gt;not&lt;/em&gt; expect what I got. Here is a question, how many queries does it take to render the following screen?&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Application-analysis_B141/image_2.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ayende.com/blog/Images/Windows-Live-Writer/Application-analysis_B141/image_thumb.png" width="940" height="693"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;The answer, believe it or no, is 17:&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Application-analysis_B141/image_4.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ayende.com/blog/Images/Windows-Live-Writer/Application-analysis_B141/image_thumb_1.png" width="771" height="409"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;You might have noticed that most of the queries look quite similar, and indeed, they &lt;em&gt;are&lt;/em&gt;. We are talking about 16(!) identical queries:&lt;/p&gt; &lt;blockquote&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;SELECT&lt;/span&gt; [Extent1].[ID] &lt;span class="kwrd"&gt;AS&lt;/span&gt; [ID],
[Extent1].[Name] &lt;span class="kwrd"&gt;AS&lt;/span&gt; [Name],
[Extent1].[Description] &lt;span class="kwrd"&gt;AS&lt;/span&gt; [Description],
[Extent1].[Picture] &lt;span class="kwrd"&gt;AS&lt;/span&gt; [Picture],
[Extent1].[RowTimeStamp] &lt;span class="kwrd"&gt;AS&lt;/span&gt; [RowTimeStamp]
&lt;span class="kwrd"&gt;FROM&lt;/span&gt; [dbo].[Category] &lt;span class="kwrd"&gt;AS&lt;/span&gt; [Extent1]&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/blockquote&gt;
&lt;p&gt;Looking at the stack trace for one of those queries led me to:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Application-analysis_B141/image_6.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ayende.com/blog/Images/Windows-Live-Writer/Application-analysis_B141/image_thumb_2.png" width="1014" height="352"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;And to this piece of code:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Application-analysis_B141/image_8.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ayende.com/blog/Images/Windows-Live-Writer/Application-analysis_B141/image_thumb_3.png" width="758" height="371"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;You might note that dynamic is used there, for what reason, I cannot even guess. Just to check, I added a ToArray() to the result of GetEntitySet, and the number of queries dropped from 17 to 2, which is more reasonable. The problem was that we passed an IQueryable to the data binding engine, which ended up evaluating the query multiple times.&lt;/p&gt;
&lt;p&gt;And &lt;a href="http://efprof.com"&gt;EF Prof&lt;/a&gt; actually warns about that, too:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Application-analysis_B141/image_10.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ayende.com/blog/Images/Windows-Live-Writer/Application-analysis_B141/image_thumb_4.png" width="763" height="120"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;At any rate, I am afraid that this project suffer from similar issues all around, it is actually too bad to serve as the bad example that I intended it to be.&lt;/p&gt;</description><link>http://ayende.com/blog/152705/application-analysis-northwind-net</link><guid>http://ayende.com/blog/152705/application-analysis-northwind-net</guid><pubDate>Fri, 30 Dec 2011 10:00:00 GMT</pubDate></item><item><title>RavenDB videos on YouTube</title><description>&lt;p&gt;We are uploading RavenDB videos to our YouTube channel on a regular basis. Here's a list of the most recent videos: &lt;p&gt;&lt;a href="http://www.youtube.com/watch?v=uk2TVs-d6sg&amp;amp;list=UUkoA7W8yn2JZHtE-zG8p8cw"&gt;Polymorphism and RavenDB&lt;/a&gt;&lt;/p&gt; &lt;p&gt; &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:5737277B-5D6D-4f48-ABFC-DD9C333F4C5D:9c244b75-1966-449b-bdec-fb981ad489f5" class="wlWriterEditableSmartContent"&gt;&lt;div&gt;&lt;object width="448" height="252"&gt;&lt;param name="movie" value="http://www.youtube.com/v/uk2TVs-d6sg?hl=en&amp;amp;hd=1"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/uk2TVs-d6sg?hl=en&amp;amp;hd=1" type="application/x-shockwave-flash" width="448" height="252"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;&lt;/div&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.youtube.com/watch?v=hJwlmVoL3oY&amp;amp;list=UUkoA7W8yn2JZHtE-zG8p8cw"&gt;The "Lost Session" @ KAN Malmo - Introduction to RavenDB&lt;/a&gt; &lt;/p&gt; &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:5737277B-5D6D-4f48-ABFC-DD9C333F4C5D:f4ffc05b-b92c-4b22-a5b9-ff040a511e2f" class="wlWriterEditableSmartContent"&gt;&lt;div&gt;&lt;object width="448" height="252"&gt;&lt;param name="movie" value="http://www.youtube.com/v/hJwlmVoL3oY?hl=en&amp;amp;hd=1"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/hJwlmVoL3oY?hl=en&amp;amp;hd=1" type="application/x-shockwave-flash" width="448" height="252"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;&lt;/div&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.youtube.com/watch?v=TEnKjeB1b38&amp;amp;list=UUkoA7W8yn2JZHtE-zG8p8cw"&gt;Virtual Brown Bag - RavenDB @ Orlando .NET User Group&lt;/a&gt; &lt;/p&gt; &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:5737277B-5D6D-4f48-ABFC-DD9C333F4C5D:1a0e1a83-b810-4cd1-936f-3e41fbfe2ab7" class="wlWriterEditableSmartContent"&gt;&lt;div&gt;&lt;object width="448" height="252"&gt;&lt;param name="movie" value="http://www.youtube.com/v/TEnKjeB1b38?hl=en&amp;amp;hd=1"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/TEnKjeB1b38?hl=en&amp;amp;hd=1" type="application/x-shockwave-flash" width="448" height="252"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;&lt;/div&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.youtube.com/watch?v=wVjy4EkSgDI&amp;amp;list=UUkoA7W8yn2JZHtE-zG8p8cw"&gt;Scaling with RavenDB&lt;/a&gt; &lt;/p&gt; &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:5737277B-5D6D-4f48-ABFC-DD9C333F4C5D:979afcaa-3d66-4c12-bda5-341dfe0f6488" class="wlWriterEditableSmartContent"&gt;&lt;div&gt;&lt;object width="448" height="252"&gt;&lt;param name="movie" value="http://www.youtube.com/v/wVjy4EkSgDI?hl=en&amp;amp;hd=1"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/wVjy4EkSgDI?hl=en&amp;amp;hd=1" type="application/x-shockwave-flash" width="448" height="252"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;&lt;/div&gt; &lt;p&gt;&lt;a href="http://www.youtube.com/watch?v=d4Fx-_7S9pU&amp;amp;list=UUkoA7W8yn2JZHtE-zG8p8cw&amp;amp;index=5&amp;amp;feature=plcp"&gt;RavenOverflow - building a StackOverflow clone with RavenDB&lt;/a&gt;&lt;/p&gt; &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:5737277B-5D6D-4f48-ABFC-DD9C333F4C5D:068732ed-15b4-4242-97b9-721d480bc906" class="wlWriterEditableSmartContent"&gt;&lt;div&gt;&lt;object width="448" height="252"&gt;&lt;param name="movie" value="http://www.youtube.com/v/d4Fx-_7S9pU?hl=en&amp;amp;hd=1"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/d4Fx-_7S9pU?hl=en&amp;amp;hd=1" type="application/x-shockwave-flash" width="448" height="252"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;&lt;/div&gt;</description><link>http://ayende.com/blog/152673/ravendb-videos-on-youtube</link><guid>http://ayende.com/blog/152673/ravendb-videos-on-youtube</guid><pubDate>Thu, 29 Dec 2011 10:00:00 GMT</pubDate></item><item><title>Windows 7 Conflict Resolution Dialog: How I hate thee</title><description>&lt;p&gt;Do you see this thing? &lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/2bd5bb0db77f_B797/image_2.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ayende.com/blog/Images/Windows-Live-Writer/2bd5bb0db77f_B797/image_thumb.png" width="466" height="510"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;I hate it. (Yes, I know that Win 8 has a better one)&lt;/p&gt; &lt;p&gt;The reason that I hate it, there is no shortcut keys for “Move and Replace”, so I have to use the freaking mouse, which takes forever.&lt;/p&gt;</description><link>http://ayende.com/blog/152801/windows-7-conflict-resolution-dialog-how-i-hate-thee</link><guid>http://ayende.com/blog/152801/windows-7-conflict-resolution-dialog-how-i-hate-thee</guid><pubDate>Thu, 29 Dec 2011 09:04:00 GMT</pubDate></item><item><title>Expanding your horizons: Actions</title><description>&lt;blockquote&gt; &lt;p&gt;In theory, there is no difference between theory and real life.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;In my previous blog post, I discussed my belief that the best value you get from learning is learning the very basic of how our machines operate. From learning about memory management in operating systems to the details of how network protocols like TCP/IP work.&lt;/p&gt; &lt;p&gt;Some of that has got to be theoretical study, actually reading about how those things work, but theory isn’t enough. I don’t care if you know the TCP specs by heart, if you haven’t actually built a real system with it, and &lt;em&gt;experienced &lt;/em&gt;the pain points, it isn’t really meaningful. The best way to learn, at least from my own experiences, is to actually do something.&lt;/p&gt; &lt;p&gt;Because that teaches you several very interesting things:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;What are the differences between the spec and what is actually implemented?&lt;/li&gt; &lt;li&gt;How to resolve common (and not so common problems)?&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;The later is probably the most important thing. I think that I learned most of what I know about HTTP in the process of building an RSS feed reader. I learned a lot about TCP from implementing a proxy system, and I did a lot of learning from a series of failed projects regarding distributed programming in general.&lt;/p&gt; &lt;p&gt;I learned a lot about file systems and how to work with file based storage from &lt;a href="http://www.amazon.com/Practical-System-Design-Dominic-Giampaolo/dp/1558604979"&gt;Practical File System Design&lt;/a&gt; and from building Rhino Queues and Rhino DHT. In retrospect, I did &lt;a href="http://ayende.com/blog/4361/the-nih-dance"&gt;a lot of very different projects&lt;/a&gt; in various areas and technologies. &lt;/p&gt; &lt;p&gt;The best way that I know to get better is to do, to fail, and to learn from what didn’t work. I don’t know of any shortcuts, although I am familiar with plenty of ways of making the road much longer (and usually not very pleasant).&lt;/p&gt; &lt;p&gt;In short, if you want to get better, pick something that you don’t know how to do, and then do it. You might fail, you likely will, but you’ll learn a lot from failing. &lt;/p&gt; &lt;p&gt;I keep drawing a blank when people ask me to suggest options for things to try building, so I thought that I would ask the readers of this blog. What sort of things do you think would be useful to build? Things that would push most people out of their comfort zone and make them learn the fundamentals of how things work.&lt;/p&gt;</description><link>http://ayende.com/blog/152641/expanding-your-horizons-actions</link><guid>http://ayende.com/blog/152641/expanding-your-horizons-actions</guid><pubDate>Wed, 28 Dec 2011 10:00:00 GMT</pubDate></item><item><title>Expanding your horizons</title><description>&lt;p&gt;One of the questions that I routinely get asked is “how do you learn”. And the answer that I keep giving is that I had accidently started learning things from the basic building blocks. I still count a C/C++ course that I took over a decade ago as one of the chief reasons why I have a good grounding in how computers actually operate. During that course, we had to do anything from building parts of the C standard library on our own to construct much of the foundation of C++ features in plain C.&lt;/p&gt; &lt;p&gt;That gave me enough understanding of how things are actually implemented to be able to grasp how things are behaving elsewhere. Digging deep into the implementation is almost never a wasted effort. And if you can’t peel away the layer of abstractions, you can’t really say that you know what you are doing. &lt;/p&gt; &lt;p&gt;For example, I count myself ignorant in all manners about WCF, but I have full confidence that I can build a system using it. Not because I understand WCF itself, but because I understand the &lt;em&gt;arena in which it plays&lt;/em&gt;. I don’t need to really understand how a certain technology works, if I already know what are the rules it has to play &lt;em&gt;with&lt;/em&gt;.&lt;/p&gt; &lt;p&gt;Picking on WCF again, if you don’t know firewalls and routers, you can’t really build a WCF system, regardless of how good your memory is about the myriad ways of configuring WCF to do you will. If you can’t use WireShark to figure out why the system is slow to respond to requests, it doesn’t matter if you can compose an WCF envelope message literally on the back of a real world envelope.&amp;nbsp; If you don’t &lt;em&gt;grok&lt;/em&gt; the Fallacies of Distributes Computing, you shouldn’t be trying to build a real system where WCF is used, regardless of whatever certificate you have from Microsoft.&lt;/p&gt; &lt;p&gt;The interesting bit is that for most of what we do, the rules are fairly consistent. We all have to play in Turing’s sand box, after all.&lt;/p&gt; &lt;p&gt;What this means is that learning the details of IP and TCP will be worth it over and over again. Understanding things like memory fetch latencies would be relevant in 5 years and in ten. Knowing what actually goes on in the system, even if it at a somewhat abstracted level is &lt;em&gt;important&lt;/em&gt;. That is what make you the master of the system, instead of its slave.&lt;/p&gt; &lt;p&gt;Some of the things that I especially value, and that is of the top of my head and isn’t a closed list are:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;TCP / UDP – how do they actually work.&lt;/li&gt; &lt;li&gt;HTTP – and implications (for example, state management).&lt;/li&gt; &lt;li&gt;The Fallacies of Distributed Computing.&lt;/li&gt; &lt;li&gt;Disk based storage – efficiently working with it, how file system works.&lt;/li&gt; &lt;li&gt;Memory management in OS and your environment.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Obviously, this is a very short list, and again, it isn’t comprehensive.&amp;nbsp; It is just meant to give you some indications for things that I have found to be useful over and over and over again.&lt;/p&gt; &lt;p&gt;That kind of knowledge isn’t something that is replaced often, and it will help you understand how anyone else has to interact with the same constraints. In fact, it often allows you to accurately guess how they solve a certain problem, because you are aware of the same alternatives that the other side had to solve.&lt;/p&gt; &lt;p&gt;In short, if you seek to be a better developer, dig deep and learn the real basic building blocks for our profession.&lt;/p&gt; &lt;p&gt;In my next post, I’ll discuss strategies for doing that.&lt;/p&gt;</description><link>http://ayende.com/blog/151553/expanding-your-horizons</link><guid>http://ayende.com/blog/151553/expanding-your-horizons</guid><pubDate>Mon, 26 Dec 2011 10:00:00 GMT</pubDate></item><item><title>Transitive Replication in RavenDB</title><description>&lt;blockquote&gt; &lt;p&gt;TLDR; &lt;/p&gt; &lt;p&gt;Replication topologies make my head hurt.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;One of our customers had an interesting requirement, several months ago:&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Transitive-Replication-in-RavenDB_E6FF/image_2.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ayende.com/blog/Images/Windows-Live-Writer/Transitive-Replication-in-RavenDB_E6FF/image_thumb.png" width="725" height="442"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Basically, he wanted to write a document at node #1, and have it replicate, &lt;em&gt;through&lt;/em&gt; node #2, to node #3. That was an easy enough change, and we did that. But then we got another issue from a different customer, who had the following topology:&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Transitive-Replication-in-RavenDB_E6FF/image_6.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ayende.com/blog/Images/Windows-Live-Writer/Transitive-Replication-in-RavenDB_E6FF/image_thumb_2.png" width="866" height="478"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;And that client problem is that when making a write to node #1, it would be replicated to nodes 2 – 4, each of which would then try to update the other two with the new replication information (it would skip node #1 because it is the source). That would cause… issues, because they already had that document in place.&lt;/p&gt; &lt;p&gt;In order to resolve that, I added a configuration option, which controls whatever the node that we replicate to should receive only documents that were modified on the current node, or whatever we need to include documents that were replicated to us from other nodes as well.&lt;/p&gt; &lt;p&gt;It is a relatively small change, code wise. Of course, documenting this, and all of the options that follows is going to be a much bigger task, because now you have to make a distinction between replicating nodes, gateway nodes, etc.&lt;/p&gt;</description><link>http://ayende.com/blog/150529/transitive-replication-in-ravendb</link><guid>http://ayende.com/blog/150529/transitive-replication-in-ravendb</guid><pubDate>Fri, 23 Dec 2011 10:00:00 GMT</pubDate></item><item><title>What is up with all those 404?</title><description>&lt;p&gt;Recently I had a spate of posts showing up, and then reporting 404. The actual reason behind that was that the server and the database disagreed with one another with regards to the timezone of the post (one was using UTC, the other local). Sorry for the trouble, and this shouldn’t happen any longer.&lt;/p&gt;</description><link>http://ayende.com/blog/152609/what-is-up-with-all-those-404</link><guid>http://ayende.com/blog/152609/what-is-up-with-all-those-404</guid><pubDate>Thu, 22 Dec 2011 20:00:00 GMT</pubDate></item><item><title>Mixing Integrated Authentication and Anonymous Authentication with PreAuthenticated = true doesn&amp;rsquo;t work</title><description>&lt;p&gt;This &lt;a href="http://stackoverflow.com/questions/1547661/ie-iis-integrated-authentication-problem"&gt;StackOverflow question&lt;/a&gt; indicate that it is half a bug and half a feature, but that it sure as hell looks like a bug to me.&lt;/p&gt; &lt;p&gt;Let us assume that we have a couple of endpoints in our application, called &lt;strong&gt;&lt;a href="http://localhost:8080/secure"&gt;http://localhost:8080/secure&lt;/a&gt; &lt;/strong&gt; and &lt;a href="http://localhost:8080/public"&gt;&lt;strong&gt;http://localhost:8080/public&lt;/strong&gt;&lt;/a&gt;. As you can imagine, the secure endpoint is… well, secure, and requires authentication. The public endpoint does not.&lt;/p&gt; &lt;p&gt;We want to optimize the number of request we make, so we specify PreAuthenticated = true; And that is where all hell break lose. &lt;/p&gt; &lt;p&gt;The problem is that it appears that when using request with entity body (in other words, PUT / POST) with PreAuthenticate = true, the .NET framework will issue a PUT / POST request with &lt;em&gt;empty body&lt;/em&gt; to the server. Presumably to get the 401 authentication information. At that point, if the endpoint that it happened to have reached is public, it will be accepted as a standard request, and processing will be tried. The problem here is that it has an &lt;em&gt;empty body&lt;/em&gt;, so that has a very strong likelihood of failing.&lt;/p&gt; &lt;p&gt;This error cost me a day and a half or so. Here is the full repro:&lt;/p&gt; &lt;blockquote&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Main()
{
&lt;span class="kwrd"&gt;new&lt;/span&gt; Thread(Server)
{
IsBackground = &lt;span class="kwrd"&gt;true&lt;/span&gt;
}.Start();
Thread.Sleep(500); &lt;span class="rem"&gt;// let the server start&lt;/span&gt;
&lt;span class="kwrd"&gt;bool&lt;/span&gt; secure = &lt;span class="kwrd"&gt;false&lt;/span&gt;;
&lt;span class="kwrd"&gt;while&lt;/span&gt; (&lt;span class="kwrd"&gt;true&lt;/span&gt;)
{
secure = !secure;
Console.Write(&lt;span class="str"&gt;"Sending: "&lt;/span&gt;);
var str = &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt;(&lt;span class="str"&gt;'a'&lt;/span&gt;, 621);
var req = WebRequest.Create(secure ? &lt;span class="str"&gt;"http://localhost:8080/secure"&lt;/span&gt; : &lt;span class="str"&gt;"http://localhost:8080/public"&lt;/span&gt;);
req.Method = &lt;span class="str"&gt;"PUT"&lt;/span&gt;;
var byteCount = Encoding.UTF8.GetByteCount(str);
req.UseDefaultCredentials = &lt;span class="kwrd"&gt;true&lt;/span&gt;;
req.Credentials = CredentialCache.DefaultCredentials;
req.PreAuthenticate = &lt;span class="kwrd"&gt;true&lt;/span&gt;;
req.ContentLength = byteCount;
&lt;span class="kwrd"&gt;using&lt;/span&gt;(var stream = req.GetRequestStream())
{
var bytes = Encoding.UTF8.GetBytes(str);
stream.Write(bytes, 0, bytes.Length);
stream.Flush();
}
req.GetResponse().Close();
}
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/blockquote&gt;
&lt;p&gt;And the server code:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Server()
{
var listener = &lt;span class="kwrd"&gt;new&lt;/span&gt; HttpListener();
listener.Prefixes.Add(&lt;span class="str"&gt;"http://+:8080/"&lt;/span&gt;);
listener.AuthenticationSchemes = AuthenticationSchemes.IntegratedWindowsAuthentication | AuthenticationSchemes.Anonymous;
listener.AuthenticationSchemeSelectorDelegate = request =&amp;gt;
{
&lt;span class="kwrd"&gt;return&lt;/span&gt; request.RawUrl.Contains(&lt;span class="str"&gt;"public"&lt;/span&gt;) ? AuthenticationSchemes.Anonymous : AuthenticationSchemes.IntegratedWindowsAuthentication;
};
listener.Start();
&lt;span class="kwrd"&gt;while&lt;/span&gt; (&lt;span class="kwrd"&gt;true&lt;/span&gt;)
{
var context = listener.GetContext();
Console.WriteLine(context.User != &lt;span class="kwrd"&gt;null&lt;/span&gt; ? context.User.Identity.Name : &lt;span class="str"&gt;"Anonymous"&lt;/span&gt;);
&lt;span class="kwrd"&gt;using&lt;/span&gt;(var reader = &lt;span class="kwrd"&gt;new&lt;/span&gt; StreamReader(context.Request.InputStream))
{
var readToEnd = reader.ReadToEnd();
&lt;span class="kwrd"&gt;if&lt;/span&gt;(&lt;span class="kwrd"&gt;string&lt;/span&gt;.IsNullOrEmpty(readToEnd))
{
Console.WriteLine(&lt;span class="str"&gt;"WTF?!"&lt;/span&gt;);
Environment.Exit(1);
}
}
context.Response.StatusCode = 200;
context.Response.Close();
}
}
&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/blockquote&gt;
&lt;p&gt;If we remove pre authenticate is set to false, everything works, but then we have twice as many requests. The annoying thing is that if it would be trying to authenticate to a public endpoint, nothing would happen, &lt;em&gt;if it were sending the bloody entity body along as well&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;This is &lt;em&gt;quite &lt;/em&gt;annoying.&lt;/p&gt;</description><link>http://ayende.com/blog/149505/mixing-integrated-authentication-and-anonymous-authentication-with-preauthenticated-true-doesnrsquo-t-work</link><guid>http://ayende.com/blog/149505/mixing-integrated-authentication-and-anonymous-authentication-with-preauthenticated-true-doesnrsquo-t-work</guid><pubDate>Thu, 22 Dec 2011 10:00:00 GMT</pubDate></item><item><title>Stupid smart code: Solution</title><description>&lt;p&gt;The reason that I said that this is very stupid code?&lt;/p&gt; &lt;blockquote&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; WriteDataToRequest(HttpWebRequest req, &lt;span class="kwrd"&gt;string&lt;/span&gt; data)
{
var byteCount = Encoding.UTF8.GetByteCount(data);
req.ContentLength = byteCount;
&lt;span class="kwrd"&gt;using&lt;/span&gt; (var dataStream = req.GetRequestStream())
{
&lt;span class="kwrd"&gt;if&lt;/span&gt;(byteCount &amp;lt;= 0x1000) &lt;span class="rem"&gt;// small size, just let the system allocate it&lt;/span&gt;
{
var bytes = Encoding.UTF8.GetBytes(data);
dataStream.Write(bytes, 0, bytes.Length);
dataStream.Flush();
&lt;span class="kwrd"&gt;return&lt;/span&gt;;
}
var buffer = &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;byte&lt;/span&gt;[0x1000];
var maxCharsThatCanFitInBuffer = buffer.Length / Encoding.UTF8.GetMaxByteCount(1);
var charBuffer = &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;char&lt;/span&gt;[maxCharsThatCanFitInBuffer];
&lt;span class="kwrd"&gt;int&lt;/span&gt; start = 0;
var encoder = Encoding.UTF8.GetEncoder();
&lt;span class="kwrd"&gt;while&lt;/span&gt; (start &amp;lt; data.Length)
{
var charCount = Math.Min(charBuffer.Length, data.Length - start);
data.CopyTo(start, charBuffer, 0, charCount);
var bytes = encoder.GetBytes(charBuffer, 0, charCount, buffer, 0, &lt;span class="kwrd"&gt;false&lt;/span&gt;);
dataStream.Write(buffer, 0, bytes);
start += charCount;
}
dataStream.Flush();
}
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/blockquote&gt;
&lt;p&gt;Because all of this lovely code can be replaced with a simple:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; WriteDataToRequest(HttpWebRequest req, &lt;span class="kwrd"&gt;string&lt;/span&gt; data)
{
req.ContentLength = Encoding.UTF8.GetByteCount(data);
&lt;span class="kwrd"&gt;using&lt;/span&gt; (var dataStream = req.GetRequestStream())
&lt;span class="kwrd"&gt;using&lt;/span&gt;(var writer = &lt;span class="kwrd"&gt;new&lt;/span&gt; StreamWriter(dataStream, Encoding.UTF8))
{
writer.Write(data);
writer.Flush();
}
}
&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/blockquote&gt;
&lt;p&gt;And that is &lt;em&gt;so&lt;/em&gt; much better.&lt;/p&gt;</description><link>http://ayende.com/blog/148481/stupid-smart-code-solution</link><guid>http://ayende.com/blog/148481/stupid-smart-code-solution</guid><pubDate>Wed, 21 Dec 2011 08:00:00 GMT</pubDate></item><item><title>Stupid smart code</title><description>&lt;p&gt;We had the following code:&lt;/p&gt; &lt;blockquote&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; WriteDataToRequest(HttpWebRequest req, &lt;span class="kwrd"&gt;string&lt;/span&gt; data)
{
var byteArray = Encoding.UTF8.GetBytes(data);
req.ContentLength = byteArray.Length;
&lt;span class="kwrd"&gt;using&lt;/span&gt; (var dataStream = req.GetRequestStream())
{
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Flush();
}
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/blockquote&gt;
&lt;p&gt;And that is a problem, because it allocates the memory twice, once for the string, once for the buffer. I changed that to this:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; WriteDataToRequest(HttpWebRequest req, &lt;span class="kwrd"&gt;string&lt;/span&gt; data)
{
var byteCount = Encoding.UTF8.GetByteCount(data);
req.ContentLength = byteCount;
&lt;span class="kwrd"&gt;using&lt;/span&gt; (var dataStream = req.GetRequestStream())
{
&lt;span class="kwrd"&gt;if&lt;/span&gt;(byteCount &amp;lt;= 0x1000) &lt;span class="rem"&gt;// small size, just let the system allocate it&lt;/span&gt;
{
var bytes = Encoding.UTF8.GetBytes(data);
dataStream.Write(bytes, 0, bytes.Length);
dataStream.Flush();
&lt;span class="kwrd"&gt;return&lt;/span&gt;;
}
var buffer = &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;byte&lt;/span&gt;[0x1000];
var maxCharsThatCanFitInBuffer = buffer.Length / Encoding.UTF8.GetMaxByteCount(1);
var charBuffer = &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;char&lt;/span&gt;[maxCharsThatCanFitInBuffer];
&lt;span class="kwrd"&gt;int&lt;/span&gt; start = 0;
var encoder = Encoding.UTF8.GetEncoder();
&lt;span class="kwrd"&gt;while&lt;/span&gt; (start &amp;lt; data.Length)
{
var charCount = Math.Min(charBuffer.Length, data.Length - start);
data.CopyTo(start, charBuffer, 0, charCount);
var bytes = encoder.GetBytes(charBuffer, 0, charCount, buffer, 0, &lt;span class="kwrd"&gt;false&lt;/span&gt;);
dataStream.Write(buffer, 0, bytes);
start += charCount;
}
dataStream.Flush();
}
}
&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/blockquote&gt;
&lt;p&gt;And I was quite proud of myself.&lt;/p&gt;
&lt;p&gt;Then I realized that I was stupid. Why?&lt;/p&gt;</description><link>http://ayende.com/blog/147457/stupid-smart-code</link><guid>http://ayende.com/blog/147457/stupid-smart-code</guid><pubDate>Tue, 20 Dec 2011 10:00:00 GMT</pubDate></item><item><title>I am turning 0x1E tomorrow</title><description>&lt;p&gt;In hex, I am still a teenager &lt;img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://ayende.com/blog/Images/Windows-Live-Writer/7a13c010ea92_8271/wlEmoticon-smile_2.png"&gt;.&lt;/p&gt; &lt;p&gt;To celebrate that, starting from the 20 Dec all the way to the new year, I decided to offer a 30% discount on all the profilers. All you need to do is to use the following coupon code:&lt;/p&gt; &lt;blockquote&gt; &lt;dl&gt; &lt;dd&gt;01E-45K2D46V6K&lt;/dd&gt;&lt;/dl&gt;&lt;/blockquote&gt; &lt;p&gt;The offer is valid for:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="http://hibernatingrhinos.com/products/UberProf"&gt;Uber Prof&lt;/a&gt; &lt;li&gt;&lt;a href="http://nhprof.com/"&gt;NHibernate Profiler&lt;/a&gt; &lt;li&gt;&lt;a href="http://efprof.com/"&gt;Entity Framework Profiler&lt;/a&gt; &lt;li&gt;&lt;a href="http://l2sprof.com/"&gt;Linq to SQL Profiler&lt;/a&gt; &lt;li&gt;&lt;a href="http://llblgenprof.com/"&gt;LLBLGen Profiler&lt;/a&gt; &lt;li&gt;&lt;a href="http://hibernateprofiler.com/"&gt;Hibernate Profiler&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://nhprof.com/commercialsupport"&gt;Commercial support for NHibernate&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;</description><link>http://ayende.com/blog/146433/i-am-turning-0x1e-tomorrow</link><guid>http://ayende.com/blog/146433/i-am-turning-0x1e-tomorrow</guid><pubDate>Mon, 19 Dec 2011 08:00:00 GMT</pubDate></item><item><title>The best argument for scale out</title><description>&lt;p&gt;I am writing a presentation, and I thought it would be interesting to get some numbers:&lt;/p&gt; &lt;table border="0" cellspacing="0" cellpadding="0"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td valign="top" width="432"&gt; &lt;p&gt;&lt;b&gt;Server &lt;/b&gt;&lt;/p&gt;&lt;/td&gt; &lt;td valign="top" width="432"&gt; &lt;p&gt;&lt;b&gt;Cost &lt;/b&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="432"&gt; &lt;p&gt;PowerEdge T110 II (Basic) – 8 GB, 3.1 Ghz Quad 4T &lt;/p&gt;&lt;/td&gt; &lt;td valign="top" width="432"&gt; &lt;p&gt;$1,350.00&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="432"&gt; &lt;p&gt;PowerEdge T110 II (Basic) – 32 GB, 3.4 Ghz Quad 8T &lt;/p&gt;&lt;/td&gt; &lt;td valign="top" width="432"&gt; &lt;p&gt;$12,103.00 &lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="432"&gt; &lt;p&gt;PowerEdge C2100 - 192 GB, 2 x 3 Ghz &lt;/p&gt;&lt;/td&gt; &lt;td width="432"&gt; &lt;p&gt;$19,960.00 &lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="432"&gt; &lt;p&gt;IBM System x3850 X5 – 8 x 2.4 Ghz, 2048 GB &lt;/p&gt;&lt;/td&gt; &lt;td valign="top" width="432"&gt; &lt;p&gt;$645,605.00&amp;nbsp; &lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="432"&gt; &lt;p&gt;Blue Gene/P – 14 teraflops, 4,096 cpus &lt;/p&gt;&lt;/td&gt; &lt;td valign="top" width="432"&gt; &lt;p&gt;$1,300,000&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="432"&gt; &lt;p&gt;K Computer (fastest super computer) - 10 petaflops, 705,024 cores, 1,377 TB &lt;/p&gt;&lt;/td&gt; &lt;td valign="top" width="432"&gt; &lt;p&gt;$10,000,000 annual &lt;i&gt;operating &lt;/i&gt;cost &lt;p&gt;No data on actual cost to build&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="864"&gt; &lt;p&gt;&lt;b&gt;And then what? &lt;/b&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;</description><link>http://ayende.com/blog/145409/the-best-argument-for-scale-out</link><guid>http://ayende.com/blog/145409/the-best-argument-for-scale-out</guid><pubDate>Fri, 16 Dec 2011 10:00:00 GMT</pubDate></item><item><title>Win Free Copies of Nhibernate 3 Beginner's Guide</title><description>&lt;p&gt;I have teamed up with Packt Publishing and we are organizing a Giveaway for&amp;nbsp; three lucky who winners stand a chance to win a copy of the NHibernate 3 Beginner’s Guide. &lt;blockquote&gt; &lt;h3&gt;Overview of Nhibernate 3 Beginner's Guide&lt;/h3&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/3bedfbea1ec6_9E3D/clip_image002_2.jpg"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="clip_image002" border="0" alt="clip_image002" src="http://ayende.com/blog/Images/Windows-Live-Writer/3bedfbea1ec6_9E3D/clip_image002_thumb.jpg" width="281" height="301"&gt;&lt;/a&gt; &lt;p&gt;· Clear, precise step-by-step directions to get you up and running quickly &lt;p&gt;· Test, profile, and monitor data access to tune the performance and make your applications fly &lt;p&gt;· Reduce hours of application development time and get better application architecture and performance &lt;p&gt;Read more about this book and download free: &lt;a href="http://link.packtpub.com/K4iYN8"&gt;Sample Chapter&lt;/a&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&lt;b&gt;How to Enter?&lt;/b&gt; &lt;p&gt;All you need to do is head on over to the &lt;a href="http://link.packtpub.com/K4iYN8"&gt;book page&lt;/a&gt; and look through the product description of this book and drop a line via the &lt;b&gt;comments below to let us know what interests you the most about this book&lt;/b&gt;. It’s that simple &lt;p&gt;Product description for NHibernate book: &lt;a href="http://www.packtpub.com/nhibernate-3-beginners-guide/book"&gt;http://www.packtpub.com/nhibernate-3-beginners-guide/book&lt;/a&gt; &lt;p&gt;Winners from the U.S. and Europe can either choose a physical copy of the book or the eBook. Users from other locales are limited to the eBook only. &lt;p&gt;&lt;strong&gt;Deadline&lt;/strong&gt; &lt;p&gt;&lt;strong&gt;&lt;br&gt;&lt;/strong&gt; &lt;p&gt;&lt;b&gt;The contest will close on 31/12/11 PT. Winners will be contacted by email, so be sure to use your real email address when you comment!&lt;/b&gt;</description><link>http://ayende.com/blog/144385/win-free-copies-of-nhibernate-3-beginners-guide</link><guid>http://ayende.com/blog/144385/win-free-copies-of-nhibernate-3-beginners-guide</guid><pubDate>Thu, 08 Dec 2011 10:00:00 GMT</pubDate></item><item><title>Rhino Service Bus &amp;amp; RavenDB integration</title><description>&lt;p&gt;One of the interesting things about Rhino Service Bus is that I explicitly designed it to work nicely with Unit of Work style data access libraries. When I did that, I worked mainly with NHibernate, but it turns out that this is really easy to integrate RavenDB as well, all you need is the following message module:&lt;/p&gt; &lt;blockquote&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; RavenDbMessageModule : IMessageModule
{
&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;readonly&lt;/span&gt; IDocumentStore documentStore;
[ThreadStatic]
&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; IDocumentSession currentSession;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; IDocumentSession CurrentSession
{
get { &lt;span class="kwrd"&gt;return&lt;/span&gt; currentSession; }
}
&lt;span class="kwrd"&gt;public&lt;/span&gt; RavenDbMessageModule(IDocumentStore documentStore)
{
&lt;span class="kwrd"&gt;this&lt;/span&gt;.documentStore = documentStore;
}
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Init(ITransport transport, IServiceBus serviceBus)
{
transport.MessageArrived += TransportOnMessageArrived;
transport.MessageProcessingCompleted += TransportOnMessageProcessingCompleted;
}
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Stop(ITransport transport, IServiceBus serviceBus)
{
transport.MessageArrived -= TransportOnMessageArrived;
transport.MessageProcessingCompleted -= TransportOnMessageProcessingCompleted;
}
&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; TransportOnMessageProcessingCompleted(CurrentMessageInformation currentMessageInformation, Exception exception)
{
&lt;span class="kwrd"&gt;if&lt;/span&gt; (currentSession != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
{
&lt;span class="kwrd"&gt;if&lt;/span&gt; (exception == &lt;span class="kwrd"&gt;null&lt;/span&gt;)
currentSession.SaveChanges();
currentSession.Dispose();
}
currentSession = &lt;span class="kwrd"&gt;null&lt;/span&gt;;
}
&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; TransportOnMessageArrived(CurrentMessageInformation currentMessageInformation)
{
&lt;span class="kwrd"&gt;if&lt;/span&gt; (currentSession == &lt;span class="kwrd"&gt;null&lt;/span&gt;)
currentSession = documentStore.OpenSession();
&lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;false&lt;/span&gt;;
}
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is fairly simple. Register to the message arrive and message processing completed events. When a message arrive, create a new session for the consumers. When the message processing is completed, and there hasn’t been any error, we call SaveChanges, and then dispose.&lt;/p&gt;
&lt;p&gt;The rest of it is pretty simple as well, we need to provide a BootStrapper:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; BootStrapper : CastleBootStrapper
{
IDocumentStore store;
&lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; ConfigureContainer()
{
store = &lt;span class="kwrd"&gt;new&lt;/span&gt; DocumentStore
{
ConnectionStringName = &lt;span class="str"&gt;"RavenDB"&lt;/span&gt;
}.Initialize();
IndexCreation.CreateIndexes(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(BootStrapper).Assembly, store);
Container.Register(
Component.For&amp;lt;IDocumentStore&amp;gt;()
.Instance(store),
Component.For&amp;lt;IMessageModule&amp;gt;()
.ImplementedBy&amp;lt;RavenDbMessageModule&amp;gt;(),
Component.For&amp;lt;IDocumentSession&amp;gt;()
.UsingFactoryMethod(() =&amp;gt; RavenDbMessageModule.CurrentSession)
);
&lt;span class="kwrd"&gt;base&lt;/span&gt;.ConfigureContainer();
}
}
&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/blockquote&gt;
&lt;p&gt;Which basically simply need to create the document store and expose it to the container. We get the document session from the current one (the one managed by the module).&lt;/p&gt;
&lt;p&gt;All in all, it is quite a thing, and it takes very little time / complexity to setup.&lt;/p&gt;</description><link>http://ayende.com/blog/143361/rhino-service-bus-amp-ravendb-integration</link><guid>http://ayende.com/blog/143361/rhino-service-bus-amp-ravendb-integration</guid><pubDate>Wed, 07 Dec 2011 10:25:00 GMT</pubDate></item><item><title>Implementing RavenDB Indexes</title><description>&lt;p&gt;I got a couple of interesting questions about RavenDB implementation, and I thought it would make a good blog post.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;Is it somewhat correct to say: When doing a map and reduce you use a dynamic or static query-index (not sure what you call them) that has compiled a c# class which will be used when deserializing the JSON to this class. This is done at server side, in memory, right? You run the query against the Lucene indexes and then deserialize the JSON and apply the projection/reduce to create the result?&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;No, this isn’t the case. We take the linq expression that makes up the statement, and then we compile that as a class. That class doesn’t represent the documents we index, it represent the &lt;em&gt;indexing operation&lt;/em&gt;. It would probably be easier to explain with an example. Here is a simple index definition:&lt;/p&gt; &lt;blockquote&gt;&lt;pre class="csharpcode"&gt;from user &lt;span class="kwrd"&gt;in&lt;/span&gt; docs.Users select &lt;span class="kwrd"&gt;new&lt;/span&gt; { user.Name }&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/blockquote&gt;
&lt;p&gt;RavenDB is going to take this code and translate into something like this:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; Raven.Abstractions;
&lt;span class="kwrd"&gt;using&lt;/span&gt; Raven.Database.Linq;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Linq;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Collections.Generic;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Collections;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System;
&lt;span class="kwrd"&gt;using&lt;/span&gt; Raven.Database.Linq.PrivateExtensions;
&lt;span class="kwrd"&gt;using&lt;/span&gt; Lucene.Net.Documents;&lt;/pre&gt;&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Index_MyIndex : AbstractViewGenerator
{
&lt;span class="kwrd"&gt;public&lt;/span&gt; Index_MyIndex()
{
&lt;span class="kwrd"&gt;this&lt;/span&gt;.ViewText = &lt;span class="str"&gt;@"from user in docs.Users select new { user.Name }"&lt;/span&gt;;
&lt;span class="kwrd"&gt;this&lt;/span&gt;.ForEntityNames.Add(&lt;span class="str"&gt;"Users"&lt;/span&gt;);
&lt;span class="kwrd"&gt;this&lt;/span&gt;.AddMapDefinition(docs =&amp;gt; from user &lt;span class="kwrd"&gt;in&lt;/span&gt; docs
&lt;span class="kwrd"&gt;where&lt;/span&gt; user[&lt;span class="str"&gt;"@metadata"&lt;/span&gt;][&lt;span class="str"&gt;"Raven-Entity-Name"&lt;/span&gt;] == &lt;span class="str"&gt;"Users"&lt;/span&gt;
select &lt;span class="kwrd"&gt;new&lt;/span&gt; { user.Name, __document_id = user.__document_id });
&lt;span class="kwrd"&gt;this&lt;/span&gt;.AddField(&lt;span class="str"&gt;"__document_id"&lt;/span&gt;);
&lt;span class="kwrd"&gt;this&lt;/span&gt;.AddField(&lt;span class="str"&gt;"Name"&lt;/span&gt;);
&lt;span class="kwrd"&gt;this&lt;/span&gt;.AddQueryParameterForMap(&lt;span class="str"&gt;"__document_id"&lt;/span&gt;);
&lt;span class="kwrd"&gt;this&lt;/span&gt;.AddQueryParameterForMap(&lt;span class="str"&gt;"Name"&lt;/span&gt;);
&lt;span class="kwrd"&gt;this&lt;/span&gt;.AddQueryParameterForReduce(&lt;span class="str"&gt;"__document_id"&lt;/span&gt;);
&lt;span class="kwrd"&gt;this&lt;/span&gt;.AddQueryParameterForReduce(&lt;span class="str"&gt;"Name"&lt;/span&gt;);
}
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/blockquote&gt;
&lt;p&gt;There is a lot going on in here, but most of it are just stuff used for internal bookkeeping for RavenDB. The important thing is the AddMapDefinition. You can see that we have taken the index definition, processed it a bit, and then we treat it like a &lt;em&gt;lambda&lt;/em&gt;. That is how RavenDB is able to go from having an index in text to processing that index in memory.&lt;/p&gt;
&lt;p&gt;Note that this has &lt;em&gt;nothing whatsoever to do with deserialization&lt;/em&gt;. That is handled by another part of RavenDB, where we use the dynamic feature (along with a host of other stuff) to make it possible to run linq queries over schema less information.&lt;/p&gt;
&lt;p&gt;Another thing to remember is that indexing is run over the documents stored in the database (input) and the results goes to Lucene (output). We never read information from Lucene as input for an index.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Could you describe how a drop of a property and a rename of a property will affect the Query-indexes?&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;If the index isn’t modified, it would try to index a missing property. That is basically a no op. In fact, we can even do nested indexing into a missing property and still have no issues, because the index code inside RavenDB is using Null Objects for most things, so you can do things like user.HelloWorld.NiceToMeeYou.Too and that would basically be translated into “don’t index me” value, instead of throwing.
&lt;p&gt;For more general information about RavenDB migrations, you can see:
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://ayende.com/blog/66562/ravendb-migrations-when-to-execute"&gt;http://ayende.com/blog/66562/ravendb-migrations-when-to-execute&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://ayende.com/blog/66563/ravendb-migrations-rolling-updates"&gt;http://ayende.com/blog/66563/ravendb-migrations-rolling-updates&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;</description><link>http://ayende.com/blog/142337/implementing-ravendb-indexes</link><guid>http://ayende.com/blog/142337/implementing-ravendb-indexes</guid><pubDate>Mon, 05 Dec 2011 10:00:00 GMT</pubDate></item><item><title>Async tests in Silverlight</title><description>&lt;p&gt;One of the things that we do is build a lot of stuff in Silverlight, usually, those things are either libraries or UI. Testing Silverlight was always a problem, but at least there is&lt;em&gt; a&lt;/em&gt; solution OOTB for that.&lt;/p&gt; &lt;p&gt;Unfortunately, the moment that you start talking about async tests (for example, you want to run a web server to check things), you need to do things like this, EnqueueCallback, EnqueueConditional and other stuff that makes the test nearly impossible to read.&lt;/p&gt; &lt;p&gt;Luckily for us, Christopher Bennage stopped here for a while and &lt;a href="http://devlicio.us/blogs/christopher_bennage/archive/2011/01/17/improving-asynchronous-tests-for-silverlight.aspx"&gt;created a solution&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;It allows you to take the following sync test:&lt;/p&gt; &lt;blockquote&gt;&lt;pre class="csharpcode"&gt;[Fact]
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; CanUpload()
{
var ms = &lt;span class="kwrd"&gt;new&lt;/span&gt; MemoryStream();
var streamWriter = &lt;span class="kwrd"&gt;new&lt;/span&gt; StreamWriter(ms);
var expected = &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt;(&lt;span class="str"&gt;'a'&lt;/span&gt;,1024);
streamWriter.Write(expected);
streamWriter.Flush();
ms.Position = 0;
var client = NewClient();
client.UploadAsync(&lt;span class="str"&gt;"abc.txt"&lt;/span&gt;, ms).Wait();
var downloadString = webClient.DownloadString(&lt;span class="str"&gt;"/files/abc.txt"&lt;/span&gt;);
Assert.Equal(expected, downloadString);
}
&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/blockquote&gt;
&lt;p&gt;And translate it to:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre class="csharpcode"&gt;[Asynchronous]
&lt;span class="kwrd"&gt;public&lt;/span&gt; IEnumerable&amp;lt;Task&amp;gt; CanUpload()
{
var ms = &lt;span class="kwrd"&gt;new&lt;/span&gt; MemoryStream();
var streamWriter = &lt;span class="kwrd"&gt;new&lt;/span&gt; StreamWriter(ms);
var expected = &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt;(&lt;span class="str"&gt;'a'&lt;/span&gt;, 1024);
streamWriter.Write(expected);
streamWriter.Flush();
ms.Position = 0;
&lt;span class="kwrd"&gt;yield&lt;/span&gt; &lt;span class="kwrd"&gt;return&lt;/span&gt; client.UploadAsync(&lt;span class="str"&gt;"abc.txt"&lt;/span&gt;, ms);
var async = webClient.DownloadStringTaskAsync(&lt;span class="str"&gt;"/files/abc.txt"&lt;/span&gt;);
&lt;span class="kwrd"&gt;yield&lt;/span&gt; &lt;span class="kwrd"&gt;return&lt;/span&gt; async;
Assert.AreEqual(expected, async.Result);
}
&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/blockquote&gt;
&lt;p&gt;It makes things &lt;em&gt;so much easier&lt;/em&gt;. To set this us, just reference &lt;a href="https://github.com/bennage/Raven-Custom-Silverlight-Unit-Test-Provider"&gt;the project&lt;/a&gt; and add the following in the App.xaml.cs file:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Application_Startup(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, StartupEventArgs e)
{
&lt;font style="background-color: #ffff00"&gt; UnitTestSystem.RegisterUnitTestProvider(&lt;span class="kwrd"&gt;new&lt;/span&gt; RavenCustomProvider());&lt;/font&gt;
RootVisual = UnitTestSystem.CreateTestPage();
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/blockquote&gt;
&lt;p&gt;And you get tests that are now easy to write and run in Silverlight.&lt;/p&gt;</description><link>http://ayende.com/blog/141313/async-tests-in-silverlight</link><guid>http://ayende.com/blog/141313/async-tests-in-silverlight</guid><pubDate>Fri, 02 Dec 2011 10:00:00 GMT</pubDate></item><item><title>Setting up a Rhino Service Bus Application: Part II&amp;ndash;One way bus</title><description>&lt;p&gt;One really nice feature of Rhino Service Bus is the notion of the one way bus. What is that? It is a miniature implementation of the bus that supports only sending messages, not receiving them. In what world is this useful?&lt;/p&gt; &lt;p&gt;It turn out, it quite a few. One way bus is usually used for web apps that just send commands / events to another system, and have no need to interact with the bus other than that, or for command line tools that just send a message, etc. The advantage of the one way bus is that you don’t need your own endpoint to use it, you can just start it, send some messages, and go away. &lt;/p&gt; &lt;p&gt;Here is how you set it up. As usual, we start from the configuration (this assumes you have the Raven.ServiceBus.Castle nuget package):&lt;/p&gt; &lt;blockquote&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;?&lt;/span&gt;&lt;span class="html"&gt;xml&lt;/span&gt; &lt;span class="attr"&gt;version&lt;/span&gt;&lt;span class="kwrd"&gt;="1.0"&lt;/span&gt;?&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;configuration&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;configSections&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;section&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="rhino.esb"&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="Rhino.ServiceBus.Config.BusConfigurationSection, Rhino.ServiceBus"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;configSections&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;rhino.esb&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;messages&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="HibernatingRhinos.Orders.Backend.Messages"&lt;/span&gt;
&lt;span class="attr"&gt;endpoint&lt;/span&gt;&lt;span class="kwrd"&gt;="msmq://localhost/Orders.Backend"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;messages&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;rhino.esb&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;configuration&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/blockquote&gt;
&lt;p&gt;You might note that we don’t have any bus/endpoint configuration, only the list of message owners.&lt;/p&gt;
&lt;p&gt;Now, the next step is just to create the actual one way bus:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre class="csharpcode"&gt;var container = &lt;span class="kwrd"&gt;new&lt;/span&gt; WindsorContainer();
&lt;span class="kwrd"&gt;new&lt;/span&gt; OnewayRhinoServiceBusConfiguration()
.UseCastleWindsor(container)
.Configure();
var onewayBus = container.Resolve&amp;lt;IOnewayBus&amp;gt;();
onewayBus.Send(&lt;span class="kwrd"&gt;new&lt;/span&gt; TestMsg
{
Name = &lt;font color="#0000ff"&gt;“ayende”&lt;/font&gt;
});
&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/blockquote&gt;
&lt;p&gt;And that is all…&lt;/p&gt;</description><link>http://ayende.com/blog/140289/setting-up-a-rhino-service-bus-application-part-iindash-one-way-bus</link><guid>http://ayende.com/blog/140289/setting-up-a-rhino-service-bus-application-part-iindash-one-way-bus</guid><pubDate>Thu, 01 Dec 2011 10:00:00 GMT</pubDate></item></channel></rss>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment