Rhino Commons

On PSake

James Kovacks introduced psake ( a power shell based build system )over a year ago, and at the time, I gave it a glance and decided that it was interesting, but not worth further investigation. This weekend, as I was restructuring my Rhino Tools project, I realized that I need to touch the build system as well. The Rhino Tools build system has been through several projects, and was originally ported from Hibernate. It is NAnt based, complex, and can do just about everything that you want expect be easily understandable. It became clear to me very quickly...

posted @ Sunday, August 30, 2009 3:02 PM | Feedback (27)

The complexity of unity

This post is about the Rhino Tools project. It has been running for a long time now, over 5 years, and amassed quite a few projects in it. I really like the codebase in the projects in Rhino Tools, but secondary aspects has been creeping in that made managing the project harder. In particular, putting all the projects in a single repository made it easy, far too easy. Projects had an easy time taking dependencies that they shouldn’t, and the entire build process was… complex, to say the least. I have been somewhat unhappily tolerant of this so...

posted @ Sunday, August 30, 2009 11:14 AM | Feedback (12)

Common infrastructure? Don't make me laugh

I am currently in the process of retiring the IRepository<T> from Rhino.Commons. I am moving it to its own set of projects, and I am not going to give it much attention in the future. Note: Backward comparability is maintained, as long as you reference the new DLLs. But why am I doing that? If there is anything that I have been thought in the last couple of years is that there is a sharp and clear distinction between technological infrastructure (web frameworks, IoC containers, OR/M) and application infrastructure (layer super type, base services, conventions). The first can...

posted @ Thursday, November 13, 2008 5:22 AM | Feedback (15)

Rhino Queues

One of the things that often come up in the NServiceBus mailing list is the request for an xcopy, zero administration, queuing service. This is especially the case when you have smart clients or want to have queues over the Internet. I decided to try to build such a thing, because it didn't seem such a hard problem. I turned out to be wrong, but it was an interesting experiment. Actually, the problem isn't that it is hard to do this, the problem was that I wanted durable queuing, and that led me to a lot of technologies that...

posted @ Friday, August 01, 2008 10:22 PM | Feedback (0)

The purpose of Rhino Commons

Nathan has posted about utility libraries and he includes Rhino Commons there as well. I don't see Rhino Commons as a utility library. At least not anymore. It certainly started its life as such, but it has grown since then. Rhino Commons represent my default architecture. This is my base when I am building applications. It has some utility classes, sure, but it contains a lot more foundation and infrastructure components than anything else.

posted @ Friday, July 18, 2008 11:55 AM | Feedback (10)

Answer: How many tests?

Two days ago I asked how many tests this method need: ///<summary> ///Get the latest published webcast ///</summary> public Webcast GetLatest(); Here is what I came up with: [TestFixture] public class WebcastRepositoryTest : DatabaseTestFixtureBase { private IWebcastRepository webcastRepository; [TestFixtureSetUp] public void TestFixtureSetup() { IntializeNHibernateAndIoC(PersistenceFramework.ActiveRecord, "windsor.boo", MappingInfo.FromAssemblyContaining<Webcast>()); } [SetUp] public void Setup() { CurrentContext.CreateUnitOfWork(); webcastRepository = IoC.Resolve<IWebcastRepository>(); } [TearDown] public void Teardown() { CurrentContext.DisposeUnitOfWork(); } [Test] public void Can_save_webcast() { var webcast = new Webcast { Name = "test", PublishDate = null }; With.Transaction(() => webcastRepository.Save(webcast)); Assert.AreNotEqual(0, webcast.Id); } [Test] public void Can_load_webcast() { var webcast = new Webcast { Name = "test", PublishDate = null }; With.Transaction(() => webcastRepository.Save(webcast)); UnitOfWork.CurrentSession.Evict(webcast); var webcast2 = webcastRepository.Get(webcast.Id); Assert.AreEqual(webcast.Id, webcast2.Id); Assert.AreEqual("test", webcast2.Name); Assert.IsNull(webcast2.PublishDate); } [Test] public void When_asking_for_latest_webcast_will_not_consider_any_that_is_not_published() { var webcast = new Webcast { Name = "test", PublishDate = null }; With.Transaction(()...

posted @ Thursday, June 12, 2008 12:52 PM | Feedback (16)

Adaptive Domain Models with Rhino Commons

Udi Dahan has been talking about this for a while now. As usual, he makes sense, but I am working in different enough context that it takes time to assimilate it. At any rate, we have been talking about this for a few days, and I finally sat down and decided that I really need to look at it with code. The result of that experiment is that I like this approach, but am still not 100% sold. The first idea is that we need to decouple the service layer from our domain implementation. But why? The...

posted @ Thursday, March 27, 2008 11:16 AM | Feedback (12)

Dealing with hierarchical structures in databases

I have a very simple requirement, I need to create a hierarchy of users' groups. So you can do something like: Administrators DBA SQLite DBA If you are a member of SQLite DBA group, you are implicitly a member of the Administrators group. In the database, it is trivial to model this: Except that then we run into the problem of dealing with the hierarchy. We can't really ask questions that involve more than one level of the hierarchy easily.  Some databases has support for hierarchical operators, but that is different from one database to...

posted @ Tuesday, January 22, 2008 1:49 AM | Feedback (24)

Rhino Igloo – MVC Framework for Web Forms

How many times have the documentation of a product told you that you really should use another product? Well, this is one such case. Rhino Igloo is an attempt to make an application that was mandated to Web Forms more palatable to work with. As such, it is heavily influenced by MonoRail and its ideas. I speak as the creator of this framework, if at all possible, prefer (mandate!) the use of MonoRail, it will be far easier, all around. Model View Controller is a problematic subject in Web Forms, because of the importance placed on the view (ASPX...

posted @ Monday, September 03, 2007 10:20 PM | Feedback (10)

Running on the trunk: Building Rhino Commons

Well, it looks like I have to share the big secret of how to keep Rhino Commons in sync with both NHibernate & Castle. The secret is never opening Visual Studio and doing it all from the command line. Here is the magic formula:D:\OSS>cd nhibernate D:\OSS\nhibernate>svn up D:\OSS\nhibernate>nant D:\OSS\nhibernate>cd.. D:\OSS>cd Castle D:\OSS\Castle>svn up D:\OSS\Castle>nant D:\OSS\Castle>copy ..\nhibernate\build\NHibernate-2.0.0.Alpha1-debug\bin\net-2.0\*.* build\net-2.0\debug /y D:\OSS\Castle>nant D:\OSS\Castle>copy ..\nhibernate\build\NHibernate-2.0.0.Alpha1-debug\bin\net-2.0\*.* ..\rhino-tools\SharedLibs\NHibernate /y D:\OSS\Castle>copy build\net-2.0\debug\*.* ..\rhino-tools\SharedLibs\Castle\*.* /y D:\OSS\Castle>cd.. D:\OSS>cd rhino-tools D:\OSS\rhino-tools>msbuild BuildAll.build

posted @ Monday, August 06, 2007 8:06 AM | Feedback (5)

Rhino ETL: Thinking about Joins & Merges

Well, I think that I have a solid foundation with the engine and syntax right now, I still have error conditions to verify, but that is something that I can handle as I go along. Now it is time to consider handling joins and merges. My initial thinking was something like: joinTransform UsersAndOrganizations: on: Left.Id.ToString().Equals(Right.UserId) transform: Row.Copy(Left) Row.OrgId = Right["Organization Id"] The problem is that while this gives me equality operation, I can't handle sets very well, I have to compare each row vs. each row, and I would like to do it better. It would also mean having to do everything in memory,...

posted @ Thursday, July 26, 2007 10:54 PM | Feedback (4)

Rhino ETL: First Code Drop

First, let me make it clear, it is not ready yet. What we have: 99% complete on the syntax Overall architecture should be stable The engine works - but I think of it as a spike, it is likely to change significantly. What remains to be done: Parallelising the work inside a pipeline Better error messages More logging More tests Transforms over sets of rows Here are a few works about how it works. The DSL is compromised of connection, source, destination and transform, which has one to one mapping with the...

posted @ Tuesday, July 24, 2007 1:24 AM | Feedback (11)

Rhino.ETL: Full Package Syntax

Okay, here is the full package syntax that I have now, which is enough to express quite a bit, I am now getting started on working on the engine itself, I am going to try the message passing architecture for now, since it is much more flexible. connection( "NorthwindConnection", ConnectionType: SqlConnection, ConnectionString: "Data Source=localhost;Initial Catalog=Northwind; Integrated Security=SSPI;" ) source Northwind, Connection="NorthwindConnection": Command: "SELECT * FROM Orders WHERE RequiredDate BETWEEN @LastUpdate AND @CurrentDate" Parameters: @LastUpdate = date.Today.AddDays(-1) @CurrentTime = ExecuteScalar("NorthwindConnection", "SELECT MAX(RequiredDate) FROM Orders") transform ToLowerCase: for column in Parameters.Columns: Row[column] = Row[column].ToLower() if Row[column] isa string destination Northwind, Connection = "NorthwindConnection": Command: """ INSERT INTO [Orders_Copy] ( [CustomerID], [EmployeeID], [OrderDate], [RequiredDate], [ShippedDate],[ShipVia], [Freight],[ShipName],[ShipAddress],[ShipCity],[ShipRegion],[ShipPostalCode], [ShipCountry] ) VALUES ( @CustomerID,@EmployeeID,@OrderDate,@RequiredDate,@ShippedDate,@ShipVia,@Freight, @ShipName,@ShipAddress,@ShipCity,@ShipRegion,@ShipPostalCode,@ShipCountry ) """ pipeline CopyOrders: Sources.Northwind >> ToLowerCase(Columns: ['ShipCity','ShipRegion']) ToLowerCase >>...

posted @ Saturday, July 21, 2007 7:10 PM | Feedback (5)

Rhino.ETL: Turning Transformations to FizzBuzz tests

Tobin Harris has asked some questions about how Rhino.ETL will handle transformations.  As you can see, I consider this something as trivial as a FizzBuzz test, which is a Good Thing, since it really should be so simple. Tobin's questions really show the current pain points in ETL processes. Remove commas from numberstransform RemoveCommas: for column in row.Columns: if row[column] isa string: row[column] = row[column].Replace(",","") Trim and convert empty string to nulltransform TrimEmptyStringToNull: for column in row.Columns: val = row[column] if val isa string: row[column] = null if val.Trim().Length == 0 Reformat UK postcodes - No idea from what format, and to what format, but let...

posted @ Saturday, July 21, 2007 2:12 AM | Feedback (4)

Rhino.ETL: Providing Answers

It would be easier to me to answer a few of the questions that has cropped up regarding Rhino.ETL. Boo vs. Ruby: Why I choose to go with Boo rather than Ruby. Very simple reasoning, my familiarity with Boo. I can make Boo do a lot of stuff already, I would have to start from scratch on Ruby. I don't see any value in one over the other, frankly, is there a reason behind the preference? NAnt ETL Tasks: The main problem I have with such an endeavor is that it is back to XML again, if I want to...

posted @ Saturday, July 21, 2007 1:22 AM | Feedback (6)

Framework building: Rhino.ETL Status Report

I am currently working on making this syntax possible, and letting ideas buzz at the back of my head regarding the implementation of the ETL engine itself. This probably requires some explanation. My idea about this is to separate the framework into two distinct layers. The core engine, which I'll talk about in a second, and the DSL syntax. One of the basic design decisions was that the DSL would be declarative, and not imperative. How does this follow, when I have something like this working: source ComplexGenerator: CommandGenerator: if Environment.GetEnvironmentVariable("production"): return "SELECT * FROM Production.Customers" else: return "SELECT * FROM Test.Customers" This certainly looks like...

posted @ Saturday, July 21, 2007 12:17 AM | Feedback (1)

Test driving Rhino.ETL

Here is the first test: [Test] public void EvaluatingScript_WithConnection_WillAddDataSourceToContext() { EtlConfigurationContext configurationContext = EtlContextBuilder.FromFile(@"Connections\connection_only.retl"); Assert.AreEqual(3, configurationContext.Connections.Count, "should have three connections"); } There is quite a bit of information just in this test, we introduced the EtlConfigurationContext class, decided that we will create it from a factory, and that we have something that is called a connection. Another decision made was the “retl” extension (Rhino ETL), but that is a side benefit. The source for this is: Connection( "Northwind", ConnectionType: SqlConnection, ConnectionString: "Data Source=localhost;Initial Catalog=Northwind; Integrated Security=SSPI;", ConcurrentConnections: 5 ) Connection( "SouthSand", ConnectionType: OracleConnection, ConnectionStringName: "SouthSand" ) Connection( "StrangeOne", ConnectionType: OracleConnection, ConnectionStringGenerator: { System.Environment.GetEnvironmentVariable("MyEnvVar") } ) You may have wondered about the last one, what does this do? Well,...

posted @ Friday, July 20, 2007 1:33 AM | Feedback (4)

Dependency Injection in Web Forms MVC

David Hayden has a post about the issue that you face when you are trying to use dependency injection in Web Forms MVC. I talked about similar issues here. He points out that this type of code is bad: protected Page_PreInit(object sender, EventArgs e) { // Constructor Injection of Data Access Service and View ICustomerDAO dao = Container.Resolve<ICustomerDAO>(): _presenter = new AddCustomerPresenter(dao,...

posted @ Thursday, June 28, 2007 1:40 AM | Feedback (6)

Rhino Commons, Repository<T> and Unit Of Work

Rhino Commons is a great collection of stuff that I gathered along the way, but never documented. There is a sample application (https://rhino-tools.svn.sourceforge.net/svnroot/rhino-tools/trunk/SampleApplications/Exesto), but not much more.  I want to spend a few minutes talking about the way the data access part of it works. This is post about how it works, not how to make it work (in other words, very little code here). Before I start, I want to mentions that Rhino Commons is (highly) opinionated software, unlike Castle or NHibernate. It is a separate place where I take what Castle & NHibernate gives me, add a mix...

posted @ Friday, June 08, 2007 1:59 AM | Feedback (14)

Rhino Mocks 2.9.6 Released

Hi, over a month without a release for Rhino Mocks is a Big Thing, I think :-) Anyway, this is a fix to a problem with the documentation message, which only work on the default expectation (because I was lazy when I wrote this?). The basic issue was that this didn't give the correct message: IAppLock mockAppLock = this.MockFactory.CreateMock<IAppLock>(); //rig up Dispose() method mockAppLock.Dispose(); LastCall     .On(mockAppLock)    .IgnoreArguments()    .Message("IAppLock should be disposed."); this.MockFactory.VerifyAll() Now it will report to you both the fact that you didn't call Dispose, as well as why you should have called dispose, which is a lot more interesting, IMO. As...

posted @ Thursday, December 07, 2006 8:37 PM | Feedback (0)

Rhino Mocks 2.9.5: Extending Rhino Mocks...

After getting a request for implementing a feature that I don't want to have in Rhino Mocks (very narrow scenario, very confusing semantics), I decided to follow my own advice and open up the API. In this case, it involved making MockRepository.CreateMockObject() and the MockRepository.CreateMockState delegate protected. Now, users of the library can extend it with their own recorders and replayers. Of course, using this require a bit of understanding of how Rhino Mocks Internals work. Basically, when Rhino Mocks is returning a type, its state is set to RecordMockState....

posted @ Saturday, November 04, 2006 10:04 PM | Feedback (0)

Rhino Tools Worth $1,000,000 ?!

I registered Rhino Tools with Ohloh (which, in Hebrew, means "On no!"), you can find the project site here. Ohloh is a project assesment site, you point it at a repository, and it does its thinks and push a nice graph in the end. Appernatly, it would take 18 years and nearly million dollars to create Rhino Tools. I'm also very surprised by the amount of code that it found, 75 thousands lines of code? I told it to estimate Castle, I wonder what it would...

posted @ Tuesday, October 17, 2006 9:03 PM | Feedback (0)

The New Repository: Rhino Tools

Following the advice from the comments, I have managed to consolidate my various OSS SVN repositories into a single one, hosted at source forge. I was quite suprised that it was so much, to tell you the truth. The repository URL is: https://svn.sourceforge.net/svnroot/rhino-tools/trunk/ To checkout, execute:svn co https://svn.sourceforge.net/svnroot/rhino-tools/trunk/ rhino-tools There is no password necceary for reads. I'll be update the various links on the site to point to the correct location soon.

posted @ Saturday, October 14, 2006 6:03 PM | Feedback (1)

PluralizingNamingStrategy for NHibenrate

One of the nicest parts of developing with NHibernate is that you can get NHibernate to generate the table from the mapping. This is extremely useful during development, when changes to the domain model and the data model are fairly common. This is even more important when you want to try something on a different database. (For instnace, you may want to use a SQLite database during testing / development, and SQL Server for production, etc). I intend to post soon about unit testing applications that uses NHibernate, and this functionality is a extremely important in...

posted @ Saturday, September 30, 2006 11:30 PM | Feedback (0)

Binsor on track (and trunk)

IoC 29 - Required to make Binsor work, has moved (with changes from Hammett), to the trunk. I've update Rhino Commons with the new changes, and now you can use it with the Windsor from Castle's trunk. Have fun...  

posted @ Saturday, September 23, 2006 10:19 PM | Feedback (1)

Thinking about APIs: Advance Usages

You may have noticed that I have create some wrappers around NHibernate, to make it easier to work with. NHibernate's API is very rich, and it can get pretty long if you are not careful. Consider the following: Session.CreateCriteria(typeof(Post))       .Add(Expression.Gt("PostedAt", DateTime.Now.AddDays(-3))) ...

posted @ Monday, September 18, 2006 9:18 PM | Feedback (4)

Rhino Commons Wiki

I opened up a section in the Wiki for Rhino Commons, mostly just descirbing what it is at the moment

posted @ Friday, September 15, 2006 10:26 PM | Feedback (2)

From NHibernate Sessions to Repository

Before: using (ISession session = _sessionManager.OpenSession()) {     IList list = session.CreateCriteria(typeof (State)) ...

posted @ Wednesday, August 09, 2006 9:39 PM | Feedback (4)

How to use Rhino Commons in ASP.Net

In the web space, the Unit of Work pattern is usually mapped to a unit of work per web request. This translate very easily to an http module, which you can find here. It configures the container automatically from a file named (by defauly) "windsor.config", and starts / dispose unit of works as part of the http pipeline. Basically, this means that you never need to worry about this. The configuration is simply: < ...

posted @ Wednesday, August 09, 2006 9:35 PM | Feedback (6)

Rhino Commons In The Open

I just realized that I was posting about it all day, but I forgot to mention where you can get it. You can browse the source repository online here, or get the source using: svn checkout svn://svn.berlios.de/rhino-mocks/trunk/rhino-commons

posted @ Sunday, July 30, 2006 5:08 PM | Feedback (1)

IoC and fluent interfaces

You may have noticed that I like to play word games with code, so here is the Inversion of Control interface in Rhino Commons: The main goal is to be able to say:ISender sender = (ISender)IoC.Container.Resolve("email"); The Initialize() method is called at application start, and will set everything up for the rest of the application. This class is to fetch the repositories, so I can generate a complex object graph and handle some interesting scenarios from the start, using generic decorators. In the end, I didn't...

posted @ Sunday, July 30, 2006 5:05 PM | Feedback (5)

More on repositories

I forgot to add that I am using a static forwarder class to get a better syntax, so I have this (after the change from RegisterSave()/RegisterDelete() to Save()/Delete() ). Another thing that I wanted to talk about was the FindAll()/FindOne() methods. While they have their overloads for working with ICriterion (and wait for a surprise there too), they also have overloads for queries. Now, I believe that one of the responsabilities of good API is to encourage good code, so I don't have any overload which...

posted @ Sunday, July 30, 2006 9:50 AM | Feedback (2)

Thinking About The Repository API

I'm currently building the API for the my Repository interface (I talked about it here). Here is what I have so far: Couple of things to note, I don't have Delete or Save methods, instead, I use RegisterSave() and RegisterDelete(), both of those make it clearer that a Unit Of Work is in action here. To make it more explicit (and to allow several repositories to use in a single Unit Of Work, I made the Unit Of Work an explicit concept: ...

posted @ Sunday, July 30, 2006 9:34 AM | Feedback (0)