Development With A Dot

Blog on development in general, and specifically on .NET



My Friends

My Links

Permanent Posts

Portuguese Communities

June 2011 - Posts

SharePoint 2010 Service Pack 1

Install updates by this order:

  1. SharePoint Foundation 2010 SP1 (not required if you install the server SP)
  2. SharePoint Foundation 2010 Language Packs SP1
  3. SharePoint Server 2010 SP1
  4. SharePoint Server 2010 SP1 Language Packs SP1
  5. June 2011 Cumulative Update

After installing any of these packages, run the SharePoint 2010 Products Configuration Wizard.

Also, you may want to read this:

Bookmark and Share

NHibernate Tools: Visual NHibernate

You probably know that I’m a big fan of Slyce Software’s Visual NHibernate. To me, it is the best tool for generating your entities and mappings from an existing database (it also allows you to go the other way, but I honestly have never used it that way).

What I like most about it:

  • Great support: folks at Slyce always listen to your suggestions, give you feedback in a timely manner, and I was even lucky enough to have some of my suggestions implemented!
  • The templating engine, which is very powerful, and more user-friendly than, for example, MyGeneration’s; one of the included templates is Sharp Architecture;
  • Advanced model validations: it even warns you about having lazy properties declared in non-lazy entities;
  • Integration with NHibernate Validator and generation of validation rules automatically based on the database, or on user-defined model settings;
  • The designer: they opted for not displaying all entities in a single screen, which I think was a good decision; has support for all inheritance strategies (table per class hierarchy, table per class, table per concrete class);
  • Generation of FluentNHibernate mappings as well as hbm.xml.

I could name others, but… why don’t you see for yourself? There is a demo version available for downloading.

By the way, I am in no way related to Slyce, I just happen to like their software!

Bookmark and Share

NHibernate Pitfalls: Private Setter on Id Property

This is part of a series of posts about NHibernate Pitfalls. See the entire collection here.

Having a private setter on an entity’s id property may seem tempting: in most cases, unless you are using id generators assigned or foreign, you never have to set its value directly.

However, keep this in mind:

  • If your entity is lazy and you want to prevent people from setting its value, make the setter protected instead of private, because it will need to be accessed from subclasses of your entity (generated by NHibernate);
  • If you use stateless sessions, you can perform some operations which, on regular sessions, require you to load an entity, without doing so, for example:
   1: using (IStatelessSession session = factory.OpenStatelessSession())
   2: {
   3:     //delete without first loading
   4:     session.Delete(new Customer { Id = 1 });
   6:     //insert without first loading
   7:     session.Insert(new Order { Customer = new Customer { Id = 1 }, Product = new Product { Id = 1 } });
   9:     //update without first loading
  10:     session.Update(new Order{ Id = 1, Product = new Product{ Id = 2 }})
  11: }

Bookmark and Share

NHibernate Pitfalls Index

Updated on March 30th

These are the posts on NHibernate pitfalls I’ve written so far. This post will be updated whenever there are more.

Bookmark and Share

NHibernate Pitfalls: Flushing Changes

This is part of a series of posts about NHibernate Pitfalls. See the entire collection here.

One common thing when saving changes with NHibernate is forgetting to flush. If you don’t flush, no changes will be sent to the database.

One of the many reasons that using a transaction is recommended is that, when the transaction commits, it automatically flushes the session, sending all updates, inserts and deletes in memory to the database – at least, if you are NOT using FlushMode.Never.

This is particularly serious when using stateless sessions, because they don’t have a Flush method (if you aren't using batching, in which case, SQL commands are sent immediately).

So, to save you from problems, always use transactions.

Bookmark and Share

Adding Custom SQL Functions to NHibernate at Runtime

The classic way to register custom SQL functions on NHibernate consists in subclassing a specific Dialect (for example, MsSql2008Dialect) and making a call to the protected method RegisterFunction somewhere in the constructor. Of course, if you use multiple dialects, you have to subclass them all.

If you want to do it without creating new classes, you have to use a bit of reflection. Here’s what I do:

   1: public static class DialectExtensions
   2: {
   3:     private static readonly MethodInfo registerFunctionMethod = typeof(Dialect).GetMethod("RegisterFunction", BindingFlags.Instance | BindingFlags.NonPublic);
   5:     public static void RegisterFunction(this Dialect dialect, String name, ISQLFunction function)
   6:     {            
   7:         registerFunctionMethod.Invoke(dialect, new Object[] { name, function });
   8:     }
  10:     public static void RegisterFunction(this ISessionFactory factory, String name, ISQLFunction function)
  11:     {
  12:         registerFunctionMethod.Invoke(GetDialect(factory), new Object[] { name, function });
  13:     }
  15:     public static Dialect GetDialect(this ISessionFactory factory)
  16:     {
  17:         return((factory as SessionFactoryImpl).Dialect);
  18:     }
  19: }

And an example, for SQL Server, is:

   1: factory.RegisterFunction("last_week", new SQLFunctionTemplate(NHibernateUtil.Date, "DATEADD(day, -7, GETDATE())"));
   3: IEnumerable<Order> lastWeekOrders = session.CreateQuery("from Order o where o.Date >= last_week()").List<Order>();

Or, slightly better:

   1: public static class DialectExtensions
   2: {
   3:     public static void RegisterFunction<T>(this ISessionFactory factory, String name, String sql)
   4:     {
   5:         IType type = NHibernateUtil.GuessType(typeof(T));
   6:         SQLFunctionTemplate template = new SQLFunctionTemplate(type, sql);
   7:         RegisterFunction(factory, name, template);
   8:     }
  10:     //...
  11: }
  13: factory.RegisterFunction<DateTime>("last_week", "DATEADD(day, -7, GETDATE())");
Bookmark and Share
LINQ to NHibernate Extensions

Giorgetti Alessandro, aka, Guardian, author of the blog PrimordialCode, has published recently some great posts on extending LINQ to NHibernate. You can read them here, here and here.

Inspired by these posts, I set out to implement some other features that LINQ to NHibernate is lacking, namely, support for the SQL CAST and COALESCE operators. It wasn’t difficult at all. Here’s what I came up with:

First, some extensions for the Object type:

   1: public static class ObjectExtensions
   2: {
   3:     public static T Coalesce<T>(this T obj, T fallback) where T: class
   4:     {
   5:         return(obj == null ? fallback : obj);
   6:     }
   8:     public static TTarget Cast<TTarget>(this Object source)
   9:     {
  10:         return ((TTarget)source);
  11:     }
  12: }

Next, the registration for the custom extensions:

   1: public class CustomLinqToHqlGeneratorsRegistry: DefaultLinqToHqlGeneratorsRegistry
   2: {
   3:     public CustomLinqToHqlGeneratorsRegistry()
   4:     {
   5:         this.RegisterGenerator(ReflectionHelper.GetMethodDefinition(() => ObjectExtensions.Coalesce<Object>(null, null)), new CoalesceHqlGeneratorForMethod());
   6:         this.RegisterGenerator(ReflectionHelper.GetMethodDefinition(() => ObjectExtensions.Cast<Object>(null)), new CastHqlGeneratorForMethod());
   7:     }
   8: }

The loquacious configuration which includes the registry:

   1: static Configuration LoquaciousBuildConfiguration<TDriver, TDialect>(String connectionStringName)
   2:             where TDriver : IDriver
   3:             where TDialect : Dialect
   4: {
   5:     Configuration cfg = new Configuration()
   6:     //.SetProperty(NHibernate.Cfg.Environment.LinqToHqlGeneratorsRegistry, typeof(CustomLinqToHqlGeneratorsRegistry).AssemblyQualifiedName)
   7:     .SetProperty(NHibernate.Cfg.Environment.GenerateStatistics, Boolean.FalseString)
   8:     .SetProperty(NHibernate.Cfg.Environment.UseQueryCache, Boolean.TrueString)
   9:     .SetProperty(NHibernate.Cfg.Environment.UseSecondLevelCache, Boolean.FalseString)
  10:     .SetProperty(NHibernate.Cfg.Environment.ShowSql, Boolean.TrueString)
  11:     .SetProperty(NHibernate.Cfg.Environment.FormatSql, Boolean.TrueString)
  12:     .SetProperty(NHibernate.Cfg.Environment.PrepareSql, Boolean.TrueString)
  13:     .SetProperty(NHibernate.Cfg.Environment.PropertyBytecodeProvider, "lcg")
  14:     .SetProperty(NHibernate.Cfg.Environment.PropertyUseReflectionOptimizer, Boolean.TrueString)
  15:     .SetProperty(NHibernate.Cfg.Environment.UseProxyValidator, Boolean.TrueString)
  16:     .Proxy(p => p.ProxyFactoryFactory<DefaultProxyFactoryFactory>())
  17:     .LinqToHqlGeneratorsRegistry<CustomLinqToHqlGeneratorsRegistry>()
  18:     .DataBaseIntegration(db =>
  19:     {
  20:         db.KeywordsAutoImport = Hbm2DDLKeyWords.AutoQuote;
  21:         db.IsolationLevel = System.Data.IsolationLevel.ReadCommitted;
  22:         db.ConnectionStringName = connectionStringName;
  23:         db.Dialect<TDialect>();
  24:         db.BatchSize = 500;
  25:         db.HqlToSqlSubstitutions = "true 1, false 0, yes 'Y', no 'N'";
  26:         db.Driver<TDriver>();
  27:     });
  29:     return (cfg);
  30: }

Now, the AST implementation for the CAST operator:

   1: class CastHqlGeneratorForMethod : BaseHqlGeneratorForMethod
   2: {
   3:     public CastHqlGeneratorForMethod()
   4:     {
   5:         this.SupportedMethods = new MethodInfo[] { ReflectionHelper.GetMethodDefinition(() => ObjectExtensions.Cast<Object>(null)) };
   6:     }
   8:     public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection<Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
   9:     {
  10:         return (treeBuilder.Cast(visitor.Visit(arguments[0]).AsExpression(), method.ReturnType));
  11:     }
  12: }

And the implementation for COALESCE:

   1: class CoalesceHqlGeneratorForMethod : BaseHqlGeneratorForMethod
   2: {
   3:     public CoalesceHqlGeneratorForMethod()
   4:     {
   5:         this.SupportedMethods = new MethodInfo[] { ReflectionHelper.GetMethodDefinition(() => ObjectExtensions.Coalesce<Object>(null, null)) };
   6:     }
   8:     public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection<Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
   9:     {
  10:         return (treeBuilder.Coalesce(visitor.Visit(arguments[0]).AsExpression(), visitor.Visit(arguments[1]).AsExpression()));
  11:     }
  12: }

Now let’s try it:

   1: Customer customerNamedSomething1 = session.Query<Customer>().Where(x => x.Name.Coalesce("SOMETHING") == "SOMETHING").FirstOrDefault();
   2: Customer customerNamedSomething2 = session.Query<Customer>().Where(x => x.Name.Cast<String>() == "SOMETHING").FirstOrDefault();

You can see that the LINQ queries are being translated to proper SQL for both cases (only tried it with SQL Server, mind you!).

OK, the examples are a bit silly, but I couldn’t think of anything else. I think you’ll get the picture, though!

Thanks to Guardian for the initial examples!

Bookmark and Share

NHibernate Pitfalls: Adding to a Bag Causes Loading
Updated. Thanks Kenneth!

This is part of a series of posts about NHibernate Pitfalls. See the entire collection here.

When adding an item to a one to many uninitialized lazy bag, all items are loaded. You would expect this to happen in a set, because NHibernate must check that the new item does not already exist in the database, but not on a bag.

The way to prevent this from happening is to specify lazy=”extra” in the mapping for the bag collection:

   1: <bag cascade="all" inverse="true" lazy="extra" name="Details">
   2:   <key column="`ORDER_ID`" />
   3:   <one-to-many class="OrderDetail" />
   4: </bag>

Bookmark and Share

More Posts