Oren Eini

CEO of RavenDB

a NoSQL Open Source Document Database

Get in touch with me:

[email protected] +972 52-548-6969

Posts: 7,527
|
Comments: 51,162
Privacy Policy · Terms
filter by tags archive
time to read 4 min | 684 words

There are occasions where it isn’t feasible or desirable to store our entity as a single document in RavenDB. A question that just came up was how to design votes for an entity using RavenDB.

The scenario is simple, we have our entity, Question (think stack overflow), which can have Up/Down votes. It would be very easy to design the system using a single document for the entity, like so:

{ //document id: questions/123
   Title: "How to handle Up/Down votes with Raven?",
   Content: "...",
   Votes: [
         { Up: true, User: "users/ayende" },
         { Up: false, User: "users/oren" },
  ]
}

As usual, the problem begins when you start to consider what happens when you want to deal with questions that may have large number of votes, or the common scenario where you just want to display the vote totals, and not pull the entire document to get that.

One option is to split things up. I guess you figured that out from the title of this blog post. The idea is to change the document structure to be:

{ //document id: questions/123
   Title: "How to handle Up/Down votes with Raven?",
   Content: "...",
}

{ //document id: questions/123/votes
   Votes: [
         { Up: true, User: "users/ayende" },
         { Up: false, User: "users/oren" },
  ]
}

Note that we have two separate documents here. Now we can load just the questions, or the questions and the votes. We still have a problem with getting the totals without loading potentially thousands of votes. It is pretty easy to solve this, however, using the following index:

from voteDoc in docs.VoteDocs
from vote in voteDoc.Votes
group vote by vote.Up into g
select new { Up = g.Key, Count = g.Count() }

Now we can query the index directly, to get the aggregated results:

session.LuceneQuery<VoteTotals>("Questions/VoteTotals")
            .SelectFields("__document_id", "Up", "Count")
            .ToList();

And if we want to get the votes themselves, they are easily available as well.

time to read 2 min | 248 words

I got a lot of interesting answers for the riddle, and here is my solution:

private static int sequentialUuidCounter;
public static Guid CreateSequentialUuid()
{
    var ticksAsBytes = BitConverter.GetBytes(DateTime.Now.Ticks);
    Array.Reverse(ticksAsBytes);
    var increment = Interlocked.Increment(ref sequentialUuidCounter);
    var currentAsBytes = BitConverter.GetBytes(increment);
    Array.Reverse(currentAsBytes);
    var bytes = new byte[16];
    Array.Copy(ticksAsBytes, 0, bytes, 0, ticksAsBytes.Length);
    Array.Copy(currentAsBytes, 0, bytes, 12, currentAsBytes.Length);
    return bytes.TransfromToGuidWithProperSorting();
}

Basically, we use the current system ticks as the 1 – 8 bytes, and a counter incremented atomically on the 12 – 16 bytes. This ensures that even concurrent calls on the same tick will have a different value.

Note that this code explicitly allows the same guid on multiple machines. You can fix that by adding the MAC address as 9 – 12 bytes, which will make this globally unique, but this isn’t something that I actually need.

Additional challenge, why am I reversing the bytes?

time to read 2 min | 291 words

The following features apply to NHProf, EFProf, L2SProf.

In general, it is strong discouraged to data bind directly to an IQueryable. Mostly, that is because data binding may actually iterate over the IQueryable several times, resulting in multiple queries being generated from something that can be done purely in memory. Worse, it is actually pretty common for data binding to result in lazy loading, and lazy loading from data binding almost always result in SELECT N+1. The profiler can now detect and warn you about such mistakes preemptively. More than that, the profiler can also now detect queries that are being generated from the views in an ASP.Net MVC application, another bad practice that I don’t like.

You can find more information about each warnings here:

WPF detection:

image

 

image

WinForms detections:

image

image

Web applications:

image

image

Silverlight SEO

time to read 1 min | 104 words

One of the reasons that people tell you to avoid Silverlight is the SEO cost. Since Justin’s blog is written in Silverlight, I thought that I might take it for a spin in Lynx, the text only browser, and see what Google sees.

My blog in Lynx:

image_thumb

Justin’s blog is Lynx. His actually looks better than mine in Lynx :-).

image_thumb[1]

time to read 3 min | 486 words

I recently got a bug report about an issue with EF Prof, apparently the application statistics would record the context being opened, but it wouldn’t show them being closed. The customer was rightfully worried about that, and wanted to know if this is a bug in his code or in EF Prof.

Not closing connections is a pretty bad idea, obviously, because you are going to hold a lot more server resources than you need.

But we couldn’t figure out what the problem was. On my end, I could see that EF Prof was recording the context close properly, but nearly the same code on the customer showed the problem. Note the word nearly. I asked for a repro of the issue, and once I had it, it took mere minutes to confirm that the problem exists.

Now was the time to find out why. The customer code was:

using(var context = new MyContext(new EntityConnection("name=MyConStr"))
{
   // do stuff
}

Now, what EF Prof tells you is a data context open & close are actually more accurately connection open & close. After some extensive study, I verified that it wasn’t my code to blame, there was a leaking connection here.

Checking a bit further, it became clear. We passed an existing connection to the context. When we dispose the context, the context asks: “Am I the owner of this connection?” And since the answer is no, it will not dispose it. It makes sense, you might want to use that connection for your own purposes, and it is pretty rude of the context to close a connection that it doesn’t own.

How can we resolve this? By giving the context the information to open the connection, but not the connection itself:

using(var context = new MyContext("name=MyConStr")
{
   // do stuff
}

This code will instruct the context to open its own connection, which it will know that it owns, so it can safely dispose it when it is disposed.

Look Ma, no leaks!

time to read 1 min | 137 words

This is a rather special request, I’ll admit. For reasons of my own, I need to find the method(s) called to actually performed data binding in WPF & WinForms.

WPF is actually quite simple:

image

WinForms, not so much. I resorted to creating a strongly typed data source and concating my extension there.

image

The answers are, by the way:

WPF:

  • at MS.Internal.Data.DataBindEngine.Task.Run(Boolean lastChance)
  • at MS.Internal.Data.DataBindEngine.Run(Object arg)

WinForms:

  • at System.Windows.Forms.CurrencyManager.SetDataSource(Object dataSource)
  • at System.Windows.Forms.BindingContext.EnsureListManager(Object dataSource, String dataMember)
time to read 2 min | 369 words

I just finished implementing a very cool feature for RavenDB, the Index Replication bundle allows you to replicate an index to a relational database.

What does this mean? Well, consider the following document:

var q = new Question
 {
     Title = "How to replicate to SQL Server?",
     Votes = new[]
     {
         new Vote{ Up = true, Comment = "Good!"}, 
         new Vote{ Up = false, Comment = "Nah!"}, 
         new Vote{ Up = true, Comment = "Nice..."}, 
     }
 };

And this index:

from q in docs.Questions
select new 
{
         Title = q.Title, 
         VoteCount = q.Votes.Count
}

With the aid of the Index Replication bundle, that index will be replicated to a relational database, giving us:

image

You can find full documentation for this feature here and the bundle itself is part of RavenDB’s unstable as of build 159.

time to read 2 min | 222 words

I got the following bug report about NH Prof:

When renaming a session, the "enter" key seems to invoke the "Cancel" rather than the "Rename Session" button - this is slightly annoying (and unexpected) behavior.

image 

But that is impossible, here is the XAML for this:

image

And as it turned out, the code is correct, and the explanation for the error is wrong, but the behavior exists.

The actual problem turned out to be that if you hit enter while the focus is on the text box, the RenameSession method will be called, but the bound value will not be modified, since the default binding mode for text boxes is on focus lost. We can fix this using:

image 

Although this is logical, considering how WPF works, I still find it surprising, I would expect this to be a common scenario that would be handled OOTB.

FUTURE POSTS

  1. RavenDB Performance: 15% improvement in one line - 16 hours from now

There are posts all the way to Dec 02, 2024

RECENT SERIES

  1. RavenDB Cloud (2):
    26 Nov 2024 - Auto scaling
  2. Challenge (75):
    01 Jul 2024 - Efficient snapshotable state
  3. Recording (14):
    19 Jun 2024 - Building a Database Engine in C# & .NET
  4. re (33):
    28 May 2024 - Secure Drop protocol
  5. Meta Blog (2):
    23 Jan 2024 - I'm a JS Developer now
View all series

Syndication

Main feed Feed Stats
Comments feed   Comments Feed Stats
}