Oren Eini

CEO of RavenDB

a NoSQL Open Source Document Database

Get in touch with me:

oren@ravendb.net +972 52-548-6969

Posts: 7,592
|
Comments: 51,223
Privacy Policy · Terms
filter by tags archive
time to read 2 min | 371 words

imageI am writing this post as a result of a discussion in the ALT.Net mailing list and DI containers in Ruby. Since I promised that I would build such a thing, it made it interesting to see how far I can minimize an IoC container.

The result is, as I said, 15 lines of significant code (ignoring blank lines or line with just curly braces).

You can see the sample model on the right. It is fairly typical model, I believe. I want to get the login controller instance without having to worry about the dependencies, and I want to do it in a non invasive way.

How can we handle that?

Well, it is pretty simple, as a matter of fact, here is the full source code for the container:

public class DemoContainer
{
	public delegate object Creator(DemoContainer container);

	private readonly Dictionary<string, object> configuration 
= new Dictionary<string, object>(); private readonly Dictionary<Type, Creator> typeToCreator
= new Dictionary<Type, Creator>(); public Dictionary<string, object> Configuration { get { return configuration; } } public void Register<T>(Creator creator) { typeToCreator.Add(typeof(T),creator); } public T Create<T>() { return (T) typeToCreator[typeof (T)](this); } public T GetConfiguration<T>(string name) { return (T) configuration[name]; } }

 Not really hard to figure out, right? And the client code is as simple:

DemoContainer container = new DemoContainer();
//registering dependecies
container.Register<IRepository>(delegate
{
	return new NHibernateRepository();
});
container.Configuration["email.sender.port"] = 1234;
container.Register<IEmailSender>(delegate
{
	return new SmtpEmailSender(container.GetConfiguration<int>("email.sender.port"));
});
container.Register<LoginController>(delegate
{
	return new LoginController(
		container.Create<IRepository>(),
		container.Create<IEmailSender>());
});

//using the container
Console.WriteLine(
	container.Create<LoginController>().EmailSender.Port
	);

I should probably mention that While this handles dependency injection quite nicely, it is absolutely not what I would consider an appropriate container to use. More on that in the next post.

time to read 2 min | 295 words

I am sharing this story because it is funny, in a sad way. And because I don't post enough bad things about myself. I also want to make it clear that this story is completely and utterly my own fault for not explaining in full what we were doing to the other guy.

A few days ago I was pairing with a new guy about some code that we had to write to generate word documents. We run into a piece of code that had fairly complex requirements. (string parsing & xpath, argh!)

I thought that this would be a good way to get the point of unit testing, since the other guy didn't get the all the edge cases when I explained them (about 7, IIRC). So we sat down and wrote a test, and we made it pass, and we wrote another test, and made it pass, etc. It was fun, it made it very clear what we were trying to achieve, etc. This post is not about the values of unit tests.

So we were done with the feature, and I move on to the next guy, trying to understand how he can make javascript do that (I still don't know, but the result is very pretty). About two hours afterward, I update my working copy with the latest source, and try to find the test that we have written. It is not there.

Hm...

I asked him were the test was, his answer was: "I deleted it, we were finished with that functionality, after all." *

* Nitpicker corner: I went and hit myself on the head for being stupid, he had no way of knowing, because I didn't explain nearly enough. I did afterward, and then I wrote the tests again.

time to read 1 min | 147 words

I hate planning. This comes from a long experience at all the problems that raise when you have faulty planning.

So, today I intended to have the class write an IoC container ,but somehow, still not sure how, we ended up building the trivial OR/M imp

https://rhino-tools.svn.sourceforge.net/svnroot/rhino-tools/trunk/SampleApplications/Course/SampleORM

 Let me say first that this is sample code, written in the span of a few hours, off the cuff coding, etc. Not meant for production... It doesn't even have identity map or unit of work.  But, it shows that it takes only a few hours to make a significant improvement in the way you work, if you are not already using the best tools out there.

And allow me to reiterate that this was written by me and the students in about two and a half hours only. I hope that this would take care of the "can't handle it" muttering.

time to read 1 min | 69 words

I am going to teach Reflection to my students tomorrow. Instead of going by the book, I think that we will implement an IoC container. Nothing like going into the nuts & bolts of it in order to make people understand how stuff works.

They are Morts, so this ties in very well into the discussion that I had on the weekend, about Mort's abilities.

I'll report on Friday...

time to read 1 min | 136 words

One of the things that I dislike about Rhino Mocks is the disconnect between methods that return a value and methods that do not. The first are handled quite naturally using Expect.Call() syntax, but the later have to use the LastCall syntax, which is often a cause of confusion.

There is little to be done there, though, that is a (valid) constraint place there by the compiler, can't do much there, right?

Jim Bolla had a different idea, and had a great suggestion, so now we can write this:

IServer mockServer = mocks.CreateMock<IMock>();
Expect.Call(delegate { mockServer.Start(); }).Throw(new InvalidConigurationException());
// rest of the test

It is also a good way to start preparing Rhino Mocks for C# 3.0.

Many thanks to Jim.

Again, the code is in the repository, and will be released soon.

time to read 3 min | 432 words

The issue of user driven entity extensibility came up in the castle users mailing list, and a very interesting discussion has started. The underlying problem is fairly well known, we want to allow the extensibility of the schema by our end users.

The scenarios that I usually think of are about extending the static schema of the application. Like adding a CustomerExternalNumber field to the Customer entity, or adding MyOwnEntity custom entity. This can be solved in a number of ways, from meta tables a schema that looks like this:

image

I am usually suspicious of such methods, and would generally prefer to go with the option of simply extending the schema at runtime by adding additional tables for the use extensions.

image The issue that came up in the list was quite different, the need was to extend each entity instance. Let us take bug tracking for instance. We need to allow the user to add different fields per each bugs. Then we need to allow to search on those extra fields, and each user can define their own fields.

Lucene came up as a way to store those extra fields, and then I had a light bulb moment. Lucene, by its nature, is a good place to store semi structure data. The basic unit of storage in Lucene is the Document. And a document is compromised of a set of fields, which can be indexed, stored or both. Hibernate Search (and NHibernate Search) uses this ability to allow us to store entity information in Lucene, which mean that we can retrieve information directly from Lucene, hitting the DB only for the missing information.

Extending this idea to also allow extra information in the Lucene store is a fairly natural extension, and extremely interesting to me. It means that I can give my users what they want (full extensibility) while keeping things very simple & clean from my point of view. Searching is built in, and easy enough that you can give the users the ability to do direct queries against that. In fact, you can even use NHibernate Search to allow even better scaling of the searching capabilities.

Reporting is also easy enough, you pull the data out, and into your entities, and report off of that, but if you want to do something more generic, it is very easy to build a Lucene query to a DataSet, which you can then hand to the reporting engine.

Exciting idea.

time to read 2 min | 224 words

imageI was scanning this article when I read noticed this bit.  A benchmark showing superior performance to another dynamic proxy implementation.  

I should mention in advance that I am impressed. I have built one from scratch, and am an active member of DP2 (and DP1, when it was relevant). That is not something that you approach easily. It is hard, damn hard. And the edge cases will kill you there.

But there are two problems that I have with this benchmark. They are mostly universal for benchmarks, actually.

First, it tests unrealistic scenario, you never use a proxy generation framework with the caching off. Well, not unless you want out of memory exceptions.

Second, it tests the wrong thing. DP2 focus is not on generation efficiency (it is important, but not the main focus), the main focus are correctness (DP2 produces verifiable code) and runtime performance. You only generate a proxy type once, this means that if you can do more in the generation phase to make it run faster at runtime, you do it.

Again, it is entirely possible that the LinFu proxies are faster at runtime as well, but I have no idea, and I don't mean to test those. Benchmarks are meaningless most of the time, you need to test for performance yourself.

time to read 14 min | 2692 words

Okay, so this is the "coding in anger" part for Rhino ETL. I need to import files into MS CRM entities. The files are standard CSV files, with the usual corruption of values that such files have. The CRM is accessed through the web services, although I am keeping aside the option of direct DB access, if I can't get the Web Services to perform any faster.

The first problem that I had was that the MS CRM Web Services are not simple services. They accept entities that are defined in the WSDL for them, not simple values. That put me in a complexity spin for a while, until I remembered that I am not working in my own little language, I am working on .NET. A quick trip to Visual Studio and an Add Web Reference + Compile later, I had integrated accessing the MS CRM into Rhino ETL.

Here is how it was done:

import CrmProxy.Crm from CrmProxy

Basically it means that I now had a dll that contains the proxy definitions for the web service, and I imported it. So it is incredibly easy to use.

Then, it was the matter of reading the file. Rhino ETL has integrated with the FileHelpers library, and I couldn't really be happier about it. There are several reasons for that, but the main one is that I run into something that the library can't handle, and I fixed that in 10 minutes, without changing the library code. Speaking of software that I like, this is one of the main criteria that I use to evaluate a piece of software. What happens when I step off the ledge? With FileHelpers, I can extend it so easily, that I really don't care about that.

Anyway, here is a part of the class definition for our file: 

[DelimitedRecord(","), IgnoreFirst]
class Customer:
      [FieldConverter(ConverterKind.Date, "dd/MM/yyyy")] 
      UpdateDate as date
      Id as int
      Name as string
      ResponsibleEmployee as Nullable of int
      [FieldConverter(Rhino.ETL.FileHelpersExtensions.DateTimeConverterWithNullValue, "dd/MM/yyyy","00/00/0000")] 
      ReceptionDate as Nullable of date

As you can see, there isn't much to it except defining the fields, types, etc.

source CustomersFile:
     execute:
            file = Read(typeof(Customer)).From(Configuration.CustomerFile)
            file.OnError(ErrorMode.SaveAndContinue)
            for customer in file:
                  print "Source ${customer.Id}"
                  SendRow( Row.FromObject(customer) ) 
            if file.HasErrors:
                  file.OutputErrors(Configuration.CustomerErrorsFile)
                  AddError("Errors have been written to ${Configuration.CustomerErrorsFile}")

Here I read from the file, use the Row.FromObject() to translate an entity into a row, and then send it forward. One amazing thing here is that FileHelpers will generate an errors file for me on demand. And that one is clear and concise and actually useful. Comparing to the amount of effort that I know are required to pull reasonable errors from SSIS file input, that is a great pleasure.

Anyway, if you missed that, I am very happy about FileHelpers.

Another thing to point out is the Configuration.CustomerFile, etc. The Configuration object is dynamically populated from a config file that you can pass to Rhino ETL (command line arg), which is a simple xml file in the format:

<configuration>
	<CustomerErrorsFile>D:\customers_errors.txt</CustomerErrorsFile>
</configuration>

Why XML? Because this seems like a place where I would want to touch with stuff like xmlpoke, etc. So it is easier to work with. It is also a flat configuration scheme, that doesn't have any semantics other than the simple key/value pair.

So, now that I have the data, I can send it to the destination:

destination Crm:
      initialize:
            Parameters.Srv = CrmService(
                  Url: Configuration.Url,
                  Credentials: NetworkCredential(
                            Configuration.Username,
                           
Configuration.Password,
                           
Configuration.Domain),
                  CallerIdValue: CallerId(CallerGuid: Guid(Configuration.CallerId)),
                  UnsafeAuthenticatedConnectionSharing: true,
                  PreAuthenticate: true
                  )

      onRow:
            theAccount = account(
                  accountnumber: Row.Id.ToString(),
                  name: Row.Name,
                  telephone1: Row.Phone,
                  telephone2: Row.Cellular,
                  telephone3: Row.AdditionalPhone,
                  fax: Row.Fax,
                  accountreceptiondate: CrmDateTime(Value: Row.ReceptionDate.ToString("yyyy-MM-ddT00:00:00")),
                  address1_city: Row.City,
                  )
            result = Parameters.Srv.Create(theAccount)
            print "Created account ${Row.Id} -> ${result}"

      cleanUp:
            Parameters.Srv.Dispose()

As you can see, we have the initialize method, which creates the service, then we instansiate an account instance, fill it with the required parameters, and go to town. It is also notable the easy translation of types from CLR types to CRM types, such as in the case of accountreceptiondate.

All in all, the only difficulities that I had during this were to make heads or tails from the inforamtion in the file, which is where I want the difficulity to lie when I am dealing with ETL processes.

time to read 2 min | 321 words

I am reading the Erlang book right now (post coming as soon as I finish it), but so far I have managed to grasp the idea of heavy use of recursion and functions for everything. It is very different from imperative languages, but I think I can make the shift.

Joe Functional, however, may have some trouble on the other way around. The following were found on production (but I'll not comment any further on their origin):

public static int CharCount(string strSource, string strToCount, bool IgnoreCase)
{
    if (IgnoreCase)
    {
        return CharCount(strSource.ToLower(), strToCount.ToLower(), true);
    }
    return CharCount(strSource, strToCount, false);
}

Let us ignore the inconsistent naming convention, the misleading function name are really think what this does...

public static string ToSingleSpace(string strParam)
{
    int index = strParam.IndexOf("  ");
    if (index == -1)
    {
        return strParam;
    }
    return ToSingleSpace(strParam.Substring(0, index) + strParam.Substring(index + 1));
}

The pattern continue, but at least I can hazard a guess about what this does, but I wouldn't want to pipe this post through it.

public static string Reverse(string strParam)
{
    if ((strParam.Length != 1) && (strParam.Length != 0))
    {
        return (Reverse(strParam.Substring(1)) + strParam.Substring(0, 1));
    }
    return strParam;
}

"Reverse a string" is something that I like to ask in interviews, but I don't suppose that this implementation will be found sufficient.

FUTURE POSTS

  1. Semantic image search in RavenDB - 2 days from now

There are posts all the way to Jul 28, 2025

RECENT SERIES

  1. RavenDB 7.1 (7):
    11 Jul 2025 - The Gen AI release
  2. Production postmorterm (2):
    11 Jun 2025 - The rookie server's untimely promotion
  3. Webinar (7):
    05 Jun 2025 - Think inside the database
  4. Recording (16):
    29 May 2025 - RavenDB's Upcoming Optimizations Deep Dive
  5. RavenDB News (2):
    02 May 2025 - May 2025
View all series

Syndication

Main feed ... ...
Comments feed   ... ...
}