Try fast search NHibernate

31 March 2009

Ensuring updates on Flush

Two assertions:

  • I like the dirty check of NHibernate because I can work without worry about explicit updates.
  • I don’t like the dirty check of NHibernate because I can’t have full control about updates and the dirty-check, in my application, is slow.

Both true ? Can we implements something to prevent Auto-Dirty-Check on flush ?

Domain

Domain

Test

Part of the configuration
<property name="generate_statistics">true</property>

I’m using NHibernate SessionFactory statistics to check some operation.

Populating DB
public void FillDb()
{
sessionFactory.EncloseInTransaction(session =>
{
for (int i = 0; i < 100; i++)
{
var reptileFamily = ReptileFamilyBuilder
.StartRecording()
.WithChildren(2)
.Build();

session.Save(ReptilesfamilyEntityName, reptileFamily);
}

for (int i = 0; i < 100; i++)
{
var humanFamily = HumanFamilyBuilder
.StartRecording()
.WithChildren(1)
.Build();

session.Save(HumanfamilyEntityName, humanFamily);
}
});
}

In a transaction I’m creating 100 Family<Reptile> and 100 Family<Human>. Each Family<Reptile> has a father, a mother and two children (total 5 entities). Each Family<Human> has a father, a mother and one children (total 4 entities). The DB will have 900 entities states (the Family is mapped to use all cascade).

The test
public void ShouldNotAutoUpdate()
{
FillDb();

using (ISession s = sessionFactory.OpenSession())
using (ITransaction tx = s.BeginTransaction())
{
var reptiles = s.CreateQuery("from ReptilesFamily")
.Future<Family<Reptile>>();

var humans = s.CreateQuery("from HumanFamily")
.Future<Family<Human>>();

ModifyAll(reptiles);
ModifyAll(humans);

sessionFactory.Statistics.Clear();

s.Update(ReptilesfamilyEntityName, reptiles.First());
s.Update(HumanfamilyEntityName, humans.First());

tx.Commit();
}

sessionFactory.Statistics.EntityUpdateCount
.Should().Be.Equal(7);

CleanDb();
}

After populate the DB I’m loading and modifying all instances of Human and Reptile (that mean 400 entities of Reptile and 300 entities of Human). The result is that I have 900 entities loaded and 700 modified in a session.

In the two session.Update I’m calling explicitly the update only for the first Family<Reptile> and the first Family<Human> (that mean only for 7 entities).

The test assertion is:

sessionFactory.Statistics.EntityUpdateCount
.Should().Be.Equal(7);

The summary is that even if I have 700 modified entities,  NHibernate should update only 7 entities because I call explicitly Update only for two families.

How change the default behavior

If you are familiar with NH2.0.0 and above you can imagine which will be the place where look… yes, Events/Listeners.

As first the configuration where you can see which events I’m using and which listeners and in which order will be executed.

            <event type="delete">

<
listener
class="DisableAutoDirtyCheck.PreDeleteEventListener, DisableAutoDirtyCheck"/>

<
listener
class="NHibernate.Event.Default.DefaultDeleteEventListener, NHibernate"/>

</
event>

<
event type="update">

<
listener
class="DisableAutoDirtyCheck.PreUpdateEventListener, DisableAutoDirtyCheck"/>

<
listener
class="NHibernate.Event.Default.DefaultUpdateEventListener, NHibernate"/>
</
event>

<
listener
class="DisableAutoDirtyCheck.PostLoadEventListener, DisableAutoDirtyCheck"
type="post-load"/>
Tricks

The real Dirty-Check happen in the DefaultFlushEntityEventListener using the session state. All entities loaded, in what is commonly named session-cache, are loaded in the Session.PersistenceContext. To be very short the PersistenceContext is a set of EntityEntry. An EntityEntry is the responsible to maintain the state and the Status of an entity.

The real trick behind all this matter is this extension:

public static class Extensions
{
private static readonly FieldInfo statusFieldInfo =
typeof (EntityEntry).GetField("status",BindingFlags.NonPublic | BindingFlags.Instance);

public static void BackSetStatus(this EntityEntry entry, Status status)
{
statusFieldInfo.SetValue(entry, status);
}
}
Listeners implementation
public class PostLoadEventListener : IPostLoadEventListener
{
public void OnPostLoad(PostLoadEvent @event)
{
EntityEntry entry = @event.Session.PersistenceContext.GetEntry(@event.Entity);
entry.BackSetStatus(Status.ReadOnly);
}
}

After load an entity, the instance is marked as ReadOnly but maintaining the loaded-state (maintain the loaded state is the reason to use the above trick).

public class PreUpdateEventListener : ISaveOrUpdateEventListener
{
public static readonly CascadingAction ResetReadOnly = new ResetReadOnlyCascadeAction();

public void OnSaveOrUpdate(SaveOrUpdateEvent @event)
{
var session = @event.Session;
EntityEntry entry = session.PersistenceContext.GetEntry(@event.Entity);
if (entry != null && entry.Persister.IsMutable && entry.Status == Status.ReadOnly)
{
entry.BackSetStatus(Status.Loaded);
CascadeOnUpdate(@event, entry.Persister, @event.Entity);
}
}

private static void CascadeOnUpdate(SaveOrUpdateEvent @event, IEntityPersister persister, object entity)
{
IEventSource source = @event.Session;
source.PersistenceContext.IncrementCascadeLevel();
try
{
new Cascade(ResetReadOnly, CascadePoint.BeforeFlush, source).CascadeOn(persister, entity);
}
finally
{
source.PersistenceContext.DecrementCascadeLevel();
}
}
}

When an entity is explicitly updated, before execute the default behavior I’m restoring the Status of the loaded entity (obviously for all the entities loaded an involved in cascade actions).

Conclusion

Can we have full control over NHibernate’s updates  ?     Yes, we can!! ;-)

Code available here.



kick it on DotNetKicks.com

25 March 2009

NUnitEx : assertion.Should().Be.Fluent();

Continuing the implementation from the previous post, NUnitEx look nice and useful.

I tried to check available features “simulating” the use of NUnitEx assertions inside some frameworks where I am involved.

Before show some new examples, I would thank to Davy, Steve and Gustavo for their help in the API definition (by the way if you find something wrong is only my fault).

New constrain chain

string something = "something";

something.Should()
.StartWith("so")
.And
.EndWith("ing")
.And
.Contain("meth");

something.Should()
.StartWith("so")
.And
.EndWith("ing")
.And
.Not.Contain("body");
var ints = new[] { 1, 2, 3 };
ints.Should()
.Have.SameSequenceAs(new[] { 1, 2, 3 })
.And
.Not.Have.SameSequenceAs(new[] { 3, 2, 1 })
.And
.Not.Be.Null()
.And
.Not.Be.Empty();

New ValueOf

ValueOf is a new property available in certain cases when we know the type during “constraints-chain”.

var instanceOfClass = new D2();

instanceOfClass.Should()
.Be.AssignableTo<D1>()
.And.Be.OfType<D2>()
.And.ValueOf.StringProperty
.Should().Be.Null();

New Actions constrains

(new Action(() => new AClass(null)))
.Should().Throw<ArgumentNullException>()
.And.
ValueOf.ParamName
.Should().Be.Equal("obj");

Obviously you can mix the classic assertion with NUnitEx API:

Assert.Throws<ArgumentNullException>(() => new AClass(null))
.ParamName.Should().Be.Equal("obj");

Exceptions assertions

These are some examples using NUnitEx syntax + LINQ

Giving:

public class SillyClass
{
public SillyClass(object obj)
{
if (obj == null)
{
throw new ArgumentException("mess",
new ArgumentNullException("mess null",
new ArgumentOutOfRangeException("obj")));
}
}
}

possible assertions are:

new Action(() => new SillyClass(null))
.Should().Throw<ArgumentException>()
.And.ValueOf.InnerExceptions()
.OfType<ArgumentOutOfRangeException>().First()
.ParamName.Should().Be.Equal("obj");

new Action(() => new SillyClass(null))
.Should().Throw<ArgumentException>()
.And.ValueOf.InnerExceptions().Select(e => e.GetType())
.Should().Contain(typeof(ArgumentOutOfRangeException));

new Action(() => new SillyClass(null))
.Should().Throw<ArgumentException>()
.And.ValueOf.InnerException
.Should().Be.OfType<ArgumentNullException>()
.And.ValueOf.Message.Should().Be.Equal("mess null");

What next

I didn’t see so many interest to have API available for NUnit2.4.8 so I would jump this step.

In term of NUnitEx internals what will be interesting is its implementation for xUnit and MbUnit, if somebody have interest I’m happy to share the project (somebody named Lars for example ;-) ).


kick it on DotNetKicks.com

22 March 2009

NUnitEx : News

After the very good feed back of the previous post, the new look of NUnitEx is:

Bollean Constraints:

actual.Should().Be.True();
actual.Should().Be.False();

Object Constraints:

actual.Should().Be.Equal(something);
actual.Should().Be.Null();
actual.Should().Be.SameInstanceAs(something);
actual.Should().Be.InstanceOf<SomeClass>();
actual.Should().Be.OfType<SomeClass>();
actual.Should().Be.AssignableFrom<SomeClass>();
actual.Should().Be.AssignableTo<SomeClass>(); 
actual.Should().Be.BinarySerializable();
actual.Should().Be.XmlSerializable();

Each constraint allow negation as : actual.Should().Not.Be.Equal(something);

Struct/Struct? Constraints

actual.Should().Be.LessThan(maxvalue);
actual.Should().Be.GreaterThan(minvalue);
actual.Should().Be.LessThanOrEqual(maxvalue);
actual.Should().Be.GreaterThanOrEqual(minvalue);
actual.Should().Be.Equal(actual);

Each constraint allow negation as : actual.Should().Not.Be.Equal(minvalue);

String Constraints

actual.Should().Be.Equal("a");
actual.Should().Be.Empty();
actual.Should().Be.Null();
actual.Should().Contain("some");
actual.Should().StartWith("some");
actual.Should().EndWith("ing");
actual.Should().Match("ome[tT]h");

Each constraint allow negation as : actual.Should().Not.Be.Equal("a string");

Enumerable Constraints

actual.Should().Have.SameSequenceAs(new[] { 1, 2, 3 });
actual.Should().Be.Null();
actual.Should().Be.Empty();
actual.Should().Be.SameInstanceAs(expected);
actual.Should().Contain(expected);
actual.Should().Have.SameValuesAs(new[] { 3, 2, 1 });
actual.Should().Have.UniqueValues();
actual.Should().Be.SubsetOf(new[] { 1, 2, 3, 4 });
actual.Should().Be.Ordered();

Each constraint allow negation as : actual.Should().Not.Have.SameSequenceAs(new[] { 3, 1 });

What next

Allow concatenation:

actual.Should().Not.Be.Null()
.And.Contain(expected)
.And.Have.UniqueValues();

Perhaps some new custom assertions for IEnumerable<T>.

Some constraints for Action as, for example:

new Action(() => new Something(null)).Should().Throw<ArgumentNullException>()
.Where.Message.Should().StartsWith("The parameter");

At last I’m studying the possibility to have the same API for others Unit-Test frameworks as xUnit, MbUnit and so on.

Remember that your feedback is very important.



kick it on DotNetKicks.com

20 March 2009

Alt.NET LA

altdotnet

Señores acaba de nacer Alt.NET en Latinoamerica o por lo menos en Argentina.

El google-group está aquí.

Estamos charlando sobre la organización de la primera reunión así que si tienen temas que les interesan están invitados a subscribirse al grupo y… deje su mensaje despues de la señal.

La verdad que con tantos proyectos Open Source, en los que colaboramos residentes en Argentina, no tener un Alt.NET acá era un desperdicio.

Señores… primer paso hecho ahora empieza el baile.

10 March 2009

NUnitEx : actual.Should().EqualTo(expected)

After this thread, I have begun a new project on GoogleCode: NUnitEx.

The intention of the project is to be a “base-line” of a possible API implementation for NUnit3.0. As me, Charlie Poole, think that  “to have the code available is different than few-words and with this project we can "test" the acceptance of a possible API based on .Net3.5” (the phrase is mine and Charlie simply said “great!”).

NUnitEx is working on-top of NUnit, so you can mix NUnit classic assertions (Assert.That(…)) with NUnitEx assertions.

The short story

The first problem was define which should be the entry point… exactly… Should(), Should().Be, ShouldBe(), Should().Not.Be, ShouldBe().Not, Should().Contains, Should().EqualTo(exepected).WithMessage(message), Should().EqualTo(exepected).Because(message) and so on. The decision I have taken, so far, is: make it less verbose as possible maintaining Should() as the entry point.

The second problem was how much complicated should be the implementation. I have studied some NUnit2.4 internals and then I have compared it with NUnit2.5… well… to be short, the decision I have taken is: make it less complicated as possible and use NUnit from a point more external as possible.

Highlight

NUnit assertions/constraints are generics and polymorphic; generics because you can apply the same to everything (or near to it), polymorphic because the same constraint may change its behavior depending on the System.Type of actual/expected. Using NUnitEx this is not ever possible.

Take a look to the follows classic assertions :

Assert.That(true, Is.Null);
Assert.That(new object(), Is.True);

You can’t write the same using NUnitEx simply because an System.Boolean can’t be null or an System.Object can’t be a System.Boolean (the intellisense is your friend).

State of the art

Commons, and more used, constraints are implemented and the framework is usable.

So far the code-coverage is 100%.

Before begin the full implementation, of all constraints, a refactoring is needed in order to manage a more deeper methods-chaining leaving all methods with, at most, one parameter.

The discussion over the API is open; feel free to express your opinion.

To run NUnitEx tests you need to download the last available release of NUnit-Gui (2.5.0) available here.

When the heavy work will be done I’m planning to open a branch to support NUnit2.4.8.

Examples

DateTime.Today.Should().LessThan(DateTime.Now);
(5.0).Should().EqualTo(5);
((uint)10).Should().GreaterThan((short)4);
5.Should().LessThan(10);
(23.0m).Should().LessThan(double.MaxValue);

int? negableInt = 10;
negableInt.Should().EqualTo(10);
5.Should().LessThan(negableInt);
11.Should().GreaterThan(negableInt);
negableInt.HasValue.Should().True();
"a".Should().EqualTo("a");
"a".Should().Not.Empty();
"a".Should().Not.Null();
"".Should().Empty();
"".Should().Not.EqualTo("a");
((string) null).Should().Null();
var ints = new[] {1, 2, 3};
ints.Should().SequenceEqualTo(ints);
ints.Should().Not.SequenceEqualTo(new[] { 3, 2, 1 });
ints.Should().Not.Null();
ints.Should().Not.Empty();
(new int[0]).Should().Empty();
((IEnumerable<int>) null).Should().Null();
var ints = new[] { 1, 2, 3 };
ints.Should().Contains(2);
ints.Should().Not.Contains(4);

Where find NUnitEx

The project is really fresh, bins and sources are available here.


kick it on DotNetKicks.com