Ayende @ Rahien

Refunds available at head office

WPF / Ayende Viewer: Part III

WPF / Ayende Viewer: Part III

The application is now composed of three screens, main one (choose categories):

(Image from clipboard).png

Select a post in a category:

(Image from clipboard).png

And view the posts in a category:

(Image from clipboard).png

Notice that you can page between the posts, this enables a very quick browsing experiance.

I commited the changes to the Rhino Tools repository (here), so you can see how I did it (not very complex). That data arrives from a sqlite database called ayende.blog using Active Record, of course.

Additional features that I want to add:

  • Add search capabilities, so I would be able to search the content / titles. Probably using SQLite full text searches. Allow to view the page results and to page through them.
  • Add tagging support, allow to browse the tags and page through tagged posts.

Not a lot of feature, eh?

Except that I have this list of things that I want to fix:

  • Give a uniform UI for the buttons in the first two screens, probaly on par with the prev/next links on the last screen.
  • Figure out control templates and replace the links on the last screen with a real control (right now it is a TextBlock with an event on MouseDown).
  • Figure out how to factor the common header into a seperate header control.
  • Add a column with the number of posts in each category.
  • Use WPF Commands instead of doing things in the events.
  • Figure out a better way to do paging than just moving between all those pages. There are advantages to this approach, so I think that I will keep them.
  • Put a meaningful title on the page, so the back button menu will look nice.
  • Put a Home button on the titlebar that will get you back to the main screen.
  • Figure out if an a really long chain of pages is a memory leak in the order that I should do something about. Yes, it is a memory leak, probably need to use KeepAlive=false, in which case the page will be discarded, and a new instance will be used when stepping back to it. As this is the default behavior, no need to do anything about it.
  • Figure out if triggers can replace the checks for next item, prev item. There isn't a way to do this properly, because there is an if pos+1 == count invovled.

WPF Question: Is this possible from mark up?

(Image from clipboard).png

"Categories:" is static text, the rest is generated via this code:

IAddChild c = Categories;//Categories is a Stack Panel with Horizontal Orientation

foreach (Category category in post.Categories)

{

      TextBlock block = new TextBlock();

      block.Text = category.Name;

      block.Style = (Style) FindResource("BigText");

      c.AddChild(block);

      TextBlock seperator = new TextBlock();

      seperator.Text = "//";

      seperator.Style = (Style)FindResource("BigText");

      seperator.Foreground = Brushes.Brown;

      c.AddChild(seperator);

}

Is there a way to do this via XAML and not from the code?

I would like to thank Tomas Restrepo for pointing me in the direct direction, this is indeed possible, like this:

<ItemsControl Name="Categories"

                    ItemsSource="{Binding}">

      <ItemsControl.ItemsPanel>

            <ItemsPanelTemplate>

                  <WrapPanel Orientation="Horizontal"/>

            </ItemsPanelTemplate>

      </ItemsControl.ItemsPanel>

      <ItemsControl.ItemTemplate>

            <DataTemplate>

                  <WrapPanel>

                        <TextBlock Text="{Binding Path=Name}" Tag="{Binding Path=CategoryId}"

                                       MouseDown="Category_Browse"

                                       Style="{StaticResource BigText}"/>

                        <TextBlock Text="//"

                                       Foreground="Brown"

                                       Style="{StaticResource BigText}"/>

                  </WrapPanel>

            </DataTemplate>

      </ItemsControl.ItemTemplate>

</ItemsControl>

Notice the ItemsSource="{Binding}", which tripped me at first. Also, note that I am binding the tag of the text blog to the ID of the category. I don't really like this, but I couldn't figure out how to bind to the current item itself.

Tags:

Published at

I did not write that code!

(Image from clipboard).png

I have no idea what happened, but I was working on an ASP.Net application (no un-managed code), hit the pause button in the debug menu, to see where the application is spending a lot of time, and I somehow ended up here. Hm... somehow I get the feeling that my team didn't write it...

Tags:

Published at

NHibernate, Logical Deletes and the Second Level Cache, Oh My!

The comments says it all, I think:

public virtual void Cancel()

{

  /*

  * NHibernate trickery:

  * Position is mapped using where="IsCancelled = 0"

  * When we cancel a Position, we are logically deleting it.

  * This plays havoc with the 2nd level cache, because the Employee.Positions

  * is cached, and the Position with the cached Id can no longer be loaded from the  
  * database.

  * Employee.Positions is mapped using cascade="all" and inverse="true"

  * So, we can remove the Position from the Employee, which will make it work

  * with the 2nd level cache, but because it is mapped as inverse="true", it

  * will not propogate the change to the database, so when we save the Position,

  * its EmployeeId will not be modified.

  */

  IsCancelled = true;

  Employee.Positions.Remove(this);

}

 

Tags:

Published at

Some interesting blog facts

Posts I have made to this blog: 10Mb, this it just the text we are talking about, not images or anything else. This is excluding comments. With comments it is close to 15Mb.

Wow!

Ayende Brower II

Take a look at this. Again, I must say that I really like WPF model. All the hurdles that I had so far were entirely my fault, and no hoods yet.

(Image from clipboard).png

Next is to support accelerator keys, paging between posts in a category and a way to tag the posts.

I am mainly doing this because I want to be able to do a quick review of all the posts in a specific category, and decide if I want to do something more with them, by the way.

With or without you: Ajax

David Hayden has a post (ASP.NET AJAX Web Controls - AJAX Experience Without Learning AJAX) that really bothers me. He talks about the different components that he tested for Ajax support, and conclude with:

I was thinking that the AJAX experience was going to be a lot of work, but my guess is that the control vendors are taking care of this for me. And, quite frankly, I didn't want to have to learn this technology in depth if I could get away with it.

Frankly, I would like to know as much about Ajax as I could get away with. The problem is that you can't escape from the complexity. You can wrap it, hide it, stash it in the attic and throw away the key, but it will come back and hunt you.

(Image from clipboard).png Complexity, meet Ajax, you are going to be best friends.

The law of leaky abstractions holds quite well for Ajax. Eventually, you will need to do something slightly beyond what is supported by the controls, or you will get an error that can't be fixed by setting a property somewhere, or you'll need to debug an issue. Those are the cases where the willful ignorance will come to haunt you.

Tags:

Published at

MonoRail Views to the uninitiated

It looks like a lot of the people working on MonoRail has at least some RubyOnRails experiance, this means that there usualy a way for people coming from mostly WebForms background to map the concepts they know to the MonoRail lingo.

Just to set the record straight, MonoRail is runing on ASP.Net platform, no perl involved.

Here is a mostly random attempt to map some of those concepts, note that I am talking about views only here;

  • Master Page
  • Master Page with multiply content areas
  • View State
  • Page LifeCycle Events
  • User Controls
  • Server Controls

Feel free to add more subjects, and I'll try to answer them as well.

Master Pages:

Master Pages are a way to share a common look and feel between pages, without duplicating the HTML. In MonoRail speak, they are called layouts, and they are settable on a controller or action granularity (or directly through code, if that strikes your fancy).

Master Pages with multiply content areas:

But wait, you are using a master page that is filled with more than a single location (for instnace, the main content and a header). In MonoRail, the same functionality is provided using a main content area ( ${ChildOutput}, for instnace ) and the use of normal variables that are filled by the view using a capture for component, like this:

Main content
<?brail component captureFor { @id : "header" }: ?>
My Header
<?brail end ?>

And in the layout:

${header}
${ChildOutput}

The output of those will be:

My Header
Main Content

View State:

View state doesn't exists, and good riddance. The web isn't stateful, the framework shouldn't lie to you and say that it is. When you need state, we have a powerful set helper classes that help provide you with the functionality that you desire.

Page LifeCycle Events:

They don't exist either, along with their complexity and the head aches that they bring. MonoRail has the following happening in a request: before filters, action, after filters, view rendering. And you usualy can ignore the filters.

User Controls:

Sometimes called partials, subviews, or macros in MonoRail speak (although each has a specific meaning), they provide the same functionality. A simple example of using one may be:

<?brail OutputSubView("faq/grid", { @source : items }) ?>

MonoRial's views can be easily embedded in an assembly, so it is trivial to take those from project to project without having to copy the sources themselves.

Server Controls

Those are called ViewComponents in MonoRail, and they provide a set of UI services for the application. Because in MonoRail the views are not working in a complex object hierarchy, it means that the view components are free to do a lot of interesting stuff that are harder to do in the WebForms model. Take for example the CaptureFor component, which output its content into a variable, which can later on be used by different parts of the views / layout.

No, no perl involved.

WPF Impressions

Since it is expected that I will learn WCF and use it extensively, I decided to take a look at WPF and see what I can do with it. Considerring that I am thinking about taking some of my posts and turning them into a series of recipes, I thought that it would be a good idea to start by creating Ayende Viewer.

(Image from clipboard).png

Not, it is not even half way complete, but it it looking good, isn't it?

Couple of notes about it:

  • It plays really nice with business objects, which make me really happy. No more DataSet-Driven-Databinding.
  • I took a look at the architecture and it looks delicious. Simple for the simple cases, possible for the complex cases. And (at least in initial exploring) I didn't find any welded hoods.
  • The tools sucks, but I say this as someone that things that it is better that the tools will be bad and the framework easy to use than the other way around. Microsoft, please, do so again in the future, give your RTM products 6 months - year in the field, before bringing the big UI guns, it will do wonder to the code quality.
  • I like the HTMLisque feeling of it...

Of course, me being me (otherwise who would I be?), I run into some interesting issues that I haven't been able to figure out for a while. It all started when I wanted to add a value conveter so I could see dates in a comprehensible form. I found out about IValueConverter, implemented it, and try to use it. No magic words could convince the application to run, it kept complaining that the type (which I just wrote) did not exists.

A long time later, I finally try to remove the reference to the converter from the XAML and compiled, it worked. Adding the references back immediately fixed this issue. As far as I can figure out, XAML is reflecting over the assembly and trying to find the type, since I haven't compiled my assembly since adding the type, it couldn't find it, and the XAML error broke my build.

Second was an issue where it would flat out refuse to acknowlenge that the resource that I added existed, some observations about the state of the moon later, I finally figured out that it is evaluating the XAML (or BAML) in order, and moved the resource defination to the top of the page.

Conclustion, I think that I will like it...

Tags:

Published at

New from ThisIsScary.com

Can you guess what this picture is?

(Image from clipboard).png

This is a partial image from a trace from a simple ASPX page, just look at the amount of controls that are involved in producing a page. Now go figure out an issue with page lifecycles of siblings please.

NHibernate and large text fields gotchas

There are two gotchas associated with working with large text fields with NHibernate.

The first is that you must specify type="StringClob" (or ColumnType = "StringClob" in Active Record), if you are using SQL Server, since NHibernate needs to set the Size property on the parameters.

The second is that if you plan of letting NHibernate generate your schema, you need to specify sql-type="NTEXT" (or SqlType="NTEXT" in Active Record), otherwise NHibernate will generate an NVARCHAR field.

Tags:

Published at

Query Express Plus

This is more of a public service announcement, Query Express Plus is a tiny, stand alone GUI for Sql Server (and other DBs). It is great for working on the server, where you can't install SSMS (or want to).

It does exactly what I want it to do and I use it quite a bit to check on my servers' behavior, put it on your keychain!

The reason for Ajax Generators

In my last post, I show how to use the Ajax Generators, but I didn't really explain why it is good to learn yet another way to do Ajax. Here is the example that I used:

page.ReplaceHtml('paginatedGrid', {@partial : 'faq/grid' })
page.VisualEffect('Highlight', 'paginatedGrid')

This will send the following to the client:

try 
{
 Element.update("paginatedGrid","gridContent");
 new Effect.Highlight('paginatedGrid', {});
}
catch(e)
{
 alert('JS error ' + e.toString());
 alert('Generated content: \nElement.update(\"paginatedGrid\",\"gridContent\");\nnew Effect.Highlight(\'paginatedGrid\', {});\n');
}

(Replace gridContent with a lot of HTML, of course). Okay, so I get nicer error handling if I have an error (always a good thing), but I don't see the value of it. Let us consider the case where we don't have something as simple as straight rendering to the client, shall we?

A good example will be in a shopping cart, if the total price of the items reach above a certain threshold, the user should get free shipping. Now that we have a conditional, the code isn't this simple to write. Add about 15 lines of JS for each condition, and you are in a world of hurt.

This is where the generators come real handy, you aren't manipulating text, but objects, which means that you get to take advantage of advance programming language constructs like conditionals and looping. Let us see how we can implement the shopping cart functionality. We will start with the logic, which in this case is sitting in the controller (probably not a good idea for non-demo scenarios):

private string[] products = { "Milk", "Honey", "Pie" };

 

public void Index()

{

       PropertyBag["cart"] = Cart;

       PropertyBag["products"] = products;

}

 

public void AddItem(int id)

{

       PropertyBag["alreadyHadfreeShipping"] = Cart.Count > 4;

       Cart.Add(products[id]);

       PropertyBag["produdct"] = products[id];

       PropertyBag["freeShipping"] = Cart.Count > 4;

       RenderView("AddItem.brailjs");

}

 

public void ClearAllItems()

{

       PropertyBag["alreadyHadfreeShipping"] = Cart.Count > 4;

       InitCart();

       RenderView("ClearAllItems.brailjs");

}

Cart is a property that exposed an ArrayList saved to the user session. You can see that we are passing the decisions to the views, to act upon. There is a business rules that says that if you buy more than 4 items you get free shipping, and that is what is going on here. No dealing with the UI at all.

Now, let us see the views, we will start with the main one, index.brail

<?brail import Boo.Lang.Builtins ?>

<h2>Demo shopping cart:</h2>

<ul>

       <?brail for i in range(products.Length):?>

              <li>

                      ${ajax.LinkToRemote(products[i],'addItem.rails?id='+i,{})}

              </li>

       <?brail end ?>

</ul>

<div id="freeShipping" style="display: none;">

       <b>You are elegible for free shipping!</b>

</div>

<h2>Purchased Products:</h2>

<p>

       ${ajax.LinkToRemote('Clear','clearAllItems.rails',{})}

</p>

<ul id="products">

       <?brail for product in cart: ?>

              <li>${product}</li>

       <?brail end ?>

</ul>

The first line shows an interesting trick, by default Brail removes the builtin namespace, because common names such as list and date exist there. Here, I want to use the range function, so I just import it and continue as usual. Beyond that, there is nNothing particulary interesting about this view, I think.

Let us see the addItem.brailjs file first, it handles updating the page to reflect the new item in the cart:

page.InsertHtml('bottom', 'products',"<li>${produdct}</li>")

if freeShipping:

      page.Show('freeShipping')

     

      if not alreadyHadfreeShipping:     

            page.VisualEffect('Highlight','freeShipping')

      end

end

As you can see, it contains conditional logic, but this logic is strictly UI focused. If the user is applicable for free shipping show it, if this is the first time, highlight the fact that they got a free shipping, so they will notice.

I would like to see similar functionality done the other way, but I do not think that I would care to write it...

Using generators gives you code that is highly maintainable in the future, and doesn't move business logic to the UI or UI logic to the business logic like often happen (by neccesaity) using other methods.

Why you should NOT reject MonoRail

I am currently trying to convince a client that we really should use MonoRail for the project. After explaining the benefits and sending a couple of tutorials in his path, I had a few minutes to sit with him about it and we talked code:

<head>

       <title>Exesto</title>

       <link rel="stylesheet"

                type="text/css"

                href="/style.css"

                media="screen, print" />

       ${Ajax.InstallScripts()}

       ${Scriptaculous.InstallScripts()}

</head>

His main objection at the moment is:

I thought that we were beyond this perl-like nonesense...

I need to work on my explaination skills...

MonoRail & Ajax Generators

I mentioned that MonoRail recently aquired Ajax Generators. The generators a are different from normal templates, because they do not generate html, but rather modify the page that was already rendered. It will be easier to exaplain with an example. Let us take the simple example of paging a grid without a full post back, shall we?  By the way, this turned out to be a lot more focused at the WebForms than I intended, more on that later.

Here is the backend of this demo:

public void Index(bool isAjax)

{

       PropertyBag["subjects"] = PaginationHelper.CreateCachedPagination(

              this, Action,15,delegate

              {

                     return new List<Subject>(Repository<Subject>.FindAll()).ToArray();

              });

       if(isAjax)

              RenderView("index.brailjs");

}

Simple, get the items from the database and store it in the cache, as well as passing it to the view. For now, please ignore the last two lines...

Now, let us a look at our view, shall we? There is a layout that I will not touch now (if you don't understand MonoRail terms, think about it as a MasterPage), but let us focus on the action's view index.brail:

<script type='text/javascript'>

       function error(e)

       {

              alert(e);

       }

       function paging(index)

      {

           var url = '/faq/index.rails';

           var pars = 'page=' + index +'&isAjax=true';       

           new Ajax.Request(url,{method: 'get', evalScripts: true, parameters: pars, onException: error});       

   

       }

</script>

<h2>Subjects for questions:</h2>

<div id='paginatedGrid'>

       <?brail OutputSubView('grid') ?>

</div>

What we have here is merely a bit of javascript and a div to put the gird in. We also use OutputSubView for the grid (again, if WebForms terms, this is something like a UserControl). The most complex part is the grid.brail view itself:

<?brail

component GridComponent, {'source':subjects}:

       section header:

?>

       <th id='header'>Id</th>

       <th id='header'>Name</th>

       <th id='header'>Browse</th>

       <?brail

       end

       section item:

?>

       <tr id='item'>

              <td>${item.Id}</td>

              <td>${item.Name}</td>

              <td>${ HtmlHelper.LinkTo('Browse','faq','showQuestions', item.Id) }</td>

       </tr>

<?brail

       end

       section alternateItem:

?>

       <tr id='alternateItem'>

              <td>${item.Id}</td>

              <td>${item.Name}</td>

              <td>${ HtmlHelper.LinkTo('Browse','faq','showQuestions', item.Id) }</td>

       </tr>

 <?brail

       end

       section link:

?>

       <a href='/faq/index.rails?page=${pageIndex}'

          onclick='paging(${pageIndex});return false;'>${title}</a>

       <?brail

       end

end

 ?>

The GridComponent is somewhere in the middle between GridView and Repeater, since it can do almost everything on its own, but let you override (for isntnace, alternateItem) parts of the rendering in place. Please pay some attention to the last section, the link. This is a pagination link that can be used to override the default behavior of moving to the next page. I am overriding it with a

Now that we have established the page, we can play with it a bit, and see that it is working great. Except that there is still the last piece of the puzzle, paging without refreshing the full page.

Go check the javascript in index.brail, notice that it is making an Ajax request to /faq/index.rails ? And that it is passing isAjax=true? No go and check the Index() method, and look at the last two lines. If this is an Ajax request, we use a different view for the output, index.brailjs;

page.ReplaceHtml('paginatedGrid', {@partial : 'faq/grid' })
page.VisualEffect('Highlight', 'paginatedGrid')

Now, what is going on here... this certianly doesn't look like any ajax framework I have ever seen...

Remember that I spoke about the ajax generators? This is it. You may think about is as a small DSL for generating the javascript to modify the page. What we have here is a call to ReplaceHtml, which will replace the content of the paginatedGrid element with something else, usually a string. But, in this case, we pass in a @partial (@symbol is identical to :symbol in Ruby, but this is a temporary syntax at the moment, I want to get rid of the {} ), which means that we ask to replace the element with the results of running the grid template.  The second line is just to provide some feedback to the user that something has changed. So, in essense, it took 4 lines of code to

But why invent a whole new syntax just to use ajax? Isn't Javascript enough? More on that next post...

And now I am feeling stupid

There is a running joke in the office about one shady guy that digs really deep into an issue. It goes like this;

Dev: I just got a NullReferenceException!
Shady Guy: Give me a second tol install the kernel debugger and we will fix it in no time.

The problem is that at the moment, I feel like I am the butt of the joke right now. For the last [undisclosed for shame reasons] hours I have been struggling with an Ajax issue that I couldn't figure out. As I mentioned before, I have very little experiance with Ajax. In light of recent additions to MonoRail, I decided that it is time to dedicate some cycles in that direction. Hammett has already ready added (awesome) support for MonoRail, and I have extended that a bit in Brail (more on that later), which deserve at least a few demos to show around.

Anyway, I already said that I had a problem, a big one. My scripts weren't being evaluated properly when they returned from the server. I debugged the server, I debugged brail, I debugged the view, at one point I even considered debugging firefox. I had enough trace tools running to suffice a small NSA lab, and enough javascript documentation to hurt the eye.

Only at the end, I started debugging the javascript library itself... after which I discovered that it will only evaluate the scripts if they were sent with "text/javascript" content-type, which I didn't use.

Damn, I hate that feeling of missing the Oh So Obvious!

Tags:

Published at

The JavaScript Database

I was asked if I could interface to an existing database, so I took a look*:

(Image from clipboard).png

Somehow I do not think that I can make it interface with NHibernate.

* To be fair, this is a client side ajax solution (think CD-ROM, not web), so this is actually a clever idea for the problem they were trying to solve.

Tags:

Published at

Late night...

It is 2AM right now, and I am chatting with someone about Inversion of Control containers... The kicker is that we are on the same timezone, sigh...

EntLib's Object Builder Issues: What am I doing wrong?

First, let me describe the scenario, I am using Object Builder in a web application to manage the services of the application. Under load, we started to get exceptions from deep within Object Builder. I should also preface this by saying that I have very little knowledge of Object Builder and it is entirely possible that I am commiting some grave error in using it.

Anyway, here is a simple wrapper for Object Builder:

public class BuilderHelper

{

    private Locator _locator = null;

 

    public BuilderHelper():this(new Locator())

    {

    }

    public BuilderHelper(Locator locator)

    {

        this._locator = locator;

        if (!_locator.Contains(typeof(ILifetimeContainer)))

            _locator.Add(typeof(ILifetimeContainer), new LifetimeContainer());

     

    }

 

    public T Build<T>()

    {

        BuilderStrategyChain chain = new BuilderStrategyChain();

        chain.Add(new SingletonStrategy());

        chain.Add(new CreationStrategy());

        PolicyList policies = new PolicyList();

 

        policies.SetDefault<ICreationPolicy>(new DefaultCreationPolicy());

 

        BuilderContext builderContext = new BuilderContext(chain, _locator, policies);

        T result;

        result = (T)builderContext.HeadOfChain.BuildUp(builderContext, typeof(T), null, null);

        return result;

 

    }

}

And here is the client code:

[TestClass]

public class StressTestingFixture

{

    private int count = 1000;

 

    [TestMethod]

    public void SimulateHeavyLoad()

    {

        ArrayList list = ArrayList.Synchronized(new ArrayList());

        ManualResetEvent wait = new ManualResetEvent(false);

        Locator locator = new Locator();

        WaitCallback callback = delegate

        {

            wait.WaitOne();//This is required so there will be a lot of threads creating objects at the same time

            try

            {

                BuilderHelper builder = new BuilderHelper(locator);

                Something i1 = builder.Build<Something>();

                if (count % 7 == 0)//need to make sure that GC Collection occurs, so it would clear the WeakRefDictionary

                    GC.Collect(2);

            }

            catch (Exception e)

            {

                string txt = e.ToString();

                Console.WriteLine(txt);

                list.Add(txt);

            }

            finally

            {

                Interlocked.Decrement(ref count);

            }

        };

        for (int i = 0; i < count; i++)

        {

            ThreadPool.QueueUserWorkItem(callback);

        }

        wait.Set();

        while (count > 0 && list.Count == 0)

            Thread.Sleep(15);

        if (list.Count > 0)

        {

            Assert.Fail((string)list[0]);

        }

    }

 

    private class Something

    {

    }

}

The error I am getting:

Assert.Fail failed. System.ArgumentException: An item with the same key has already been added.
   at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource)
   at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
   at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value)
   at Microsoft.Practices.ObjectBuilder.WeakRefDictionary`2.Add(TKey key, TValue value) in C:\Documents and Settings\orene\Desktop\Microsoft Enterprise Library January 2006\src\ObjectBuilder\Utility\WeakRefDictionary.cs:line 82
   at Microsoft.Practices.ObjectBuilder.Locator.Add(Object key, Object value) in C:\Documents and Settings\orene\Desktop\Microsoft Enterprise Library January 2006\src\ObjectBuilder\Location\Locator.cs:line 59
   at BuilderHelper..ctor(Locator locator) in C:\Documents and Settings\orene\Desktop\Microsoft Enterprise Library January 2006\UnitTests\ObjectBuilder\BuilderFixture.cs:line 42
   at StressTestingFixture.<>c__DisplayClass1.<SimulateHeavyLoad>b__0(Object ) in C:\Documents and Settings\orene\Desktop\Microsoft Enterprise Library January 2006\UnitTests\ObjectBuilder\StressTestingFixture.cs:line 80

To say that this is worrying is a major understatement...

Any EntLib experts that can shed some light into this?

MonoRail, Active Record & Repository Sample Application

Since I was asked, here is a demo application for using Active Record and Repository<T>.  Please note that this is an internal application that I use to merely test some ideas, so it is a bit rough, and there isn't any real functionality.

  • The more interesting stuff for ActiveRecord & Repository<T> can be found in the FaqController.
  • The entities are in Exesto.Model assembly, with all the usual attributes.
  • A UnitOfWorkApplication (HttpApplication) handles the scopes (using IUnitOfWorkFactory).
  • Configuring Windsor is done using Binsor, in Windsor.boo
  • Visit /construct/database.rails to create the database.

Here are the links to the source online: