Contents tagged with NHibernate

  • Lesser-Known NHibernate Features: Result Transformers

    A result transformer, in NHibernate, is some class that implements the IResultTransformer interface:

       1: public interface IResultTransformer
       2: {
       3:     IList TransformList(IList collection);
       4:     Object TransformTuple(Object[] tuple, String[] aliases);
       5: }

    Most query APIs, except LINQ, support specifying a result transformer. So, what is a result transformer used for? Just what the name says: it turns the values obtained from a query into some object. Normally, we just let NHibernate transform these values into instances of our entities, but we may want to do something different, either because we haven’t mapped some class that we want to use, or because we are not returning all of the entity’s properties, etc.

    NHibernate includes some result transformers:

    • AliasToBeanResultTransformer: allows to transform a result to a user specified class which will be populated via setter methods or fields matching the alias names;
    • AliasToBeanConstructorResultTransformer: identical to AliasToBeanResultTransformer, but we specify a constructor for creating new instances of the target class;
    • AliasToEntityMapResultTransformer: returns a dictionary where the keys are the aliases and the values the corresponding columns;
    • AliasedTupleSubsetResultTransformer: ignores a tuple element if its corresponding alias is null;
    • CacheableResultTransformer: used to transform tuples to a value(s) that can be cached;
    • DistinctRootEntityResultTransformer: for joined queries, returns distinct root entities only;
    • PassThroughResultTransformer: just returns the row as it was obtained from the database;
    • RootEntityResultTransformer; returns the root entity of a joined query;
    • ToListResultTransformer: transforms each result row from a tuple into a IList, such that what you end up with is a IList of ILists.


    All of these can be obtained from static properties in class NHibernate.Transform.Transformers. NHibernate implicitly uses some of these, for example, LINQ queries always use DistinctRootEntityResultTransformer.

    It is easy to build our own transformer. Have a look at the following example:

       1: public class ExpressionsResultTransformer : IResultTransformer
       2: {
       3:     private readonly Type type;
       4:     private readonly Func<Object> constructorFunc;
       5:     private readonly ConstructorInfo constructor;
       6:     private readonly Object[] parameters;
       7:     private readonly Dictionary<Int32, String> expressions = new Dictionary<Int32, String>();
       8:     private PropertyDescriptorCollection props;
       9:  
      10:     public ExpressionsResultTransformer(ConstructorInfo constructor, params Object[] parameters)
      11:     {
      12:         this.constructor = constructor;
      13:         this.parameters = parameters;
      14:     }
      15:  
      16:     public ExpressionsResultTransformer(Func<Object> constructorFunc)
      17:     {
      18:         this.constructorFunc = constructorFunc;
      19:     }
      20:  
      21:     public ExpressionsResultTransformer(Type type)
      22:     {
      23:         this.type = type;
      24:     }
      25:  
      26:     private Object CreateInstance()
      27:     {
      28:         if (this.type != null)
      29:         {
      30:             return (Activator.CreateInstance(this.type));
      31:         }
      32:         else if (this.constructorFunc != null)
      33:         {
      34:             return (this.constructorFunc());
      35:         }
      36:         else
      37:         {
      38:             return (this.constructor.Invoke(this.parameters));
      39:         }
      40:     }
      41:  
      42:     public ExpressionsResultTransformer Add(Int32 index, String property)
      43:     {
      44:         this.expressions[index] = property;
      45:         return (this);
      46:     }
      47:  
      48:     public ExpressionsResultTransformer Add(params String[] properties)
      49:     {
      50:         foreach (var property in properties)
      51:         {
      52:             this.Add(property);
      53:         }
      54:  
      55:         return (this);
      56:     }
      57:  
      58:     public ExpressionsResultTransformer Add(String property)
      59:     {
      60:         var max = this.expressions.Keys.DefaultIfEmpty(-1).Max();
      61:         return (this.Add(max + 1, property));
      62:     }
      63:  
      64:     public static ExpressionsResultTransformer Add<T>(params String[] properties) where T : new()
      65:     {
      66:         return (new ExpressionsResultTransformer<T>().Add(properties));
      67:     }
      68:  
      69:     #region IResultTransformer Members
      70:  
      71:     IList IResultTransformer.TransformList(IList collection)
      72:     {
      73:         return (collection);
      74:     }
      75:  
      76:     Object IResultTransformer.TransformTuple(Object[] tuple, String[] aliases)
      77:     {
      78:         var entity = this.CreateInstance();
      79:  
      80:         if (this.props == null)
      81:         {
      82:             this.props = TypeDescriptor.GetProperties(entity);
      83:         }
      84:  
      85:         foreach (var expression in this.expressions)
      86:         {
      87:             this.props[expression.Value].SetValue(entity, tuple[expression.Key]);
      88:         }
      89:  
      90:         return (entity);
      91:     }
      92:  
      93:     #endregion
      94: }
      95:  
      96: public sealed class ExpressionsResultTransformer<T> : ExpressionsResultTransformer where T : new()
      97: {
      98:     public ExpressionsResultTransformer() : base(typeof(T))
      99:     {
     100:     }
     101:  
     102:     public ExpressionsResultTransformer(Func<T> constructor) : base(new Func<Object>(() => (Object) constructor()))
     103:     {
     104:     }
     105:  
     106:     public ExpressionsResultTransformer(ConstructorInfo constructor, params Object[] parameters) : base(constructor, parameters)
     107:     {
     108:     }
     109: }

    The TransformTuple method is the one used to turn each returned record into an instance of something. TransformList is called at the end, when all the records have been processed.

    The ExpressionResultTransformer class allows us to select which indexes, in the database record, map to which properties in some entity. For our convenience, it offers a number of options to construct an instance (type, constructor + parameters and delegate). We would use it like this:

       1: var products = session.CreateSQLQuery("select p.Name, p.Price, p.ProductId from Product p").SetResultTransformer(ExpressionsResultTransformer.Add<Product>("Name", "Price", "ProductId")).List<Product>();

    Read more...

  • Getting the SQL for HQL and Criteria Queries

    OK, so, I already showed how we can get the SQL that was generated from a LINQ query. Of course, we can do the same for both HQL and Criteria APIs as well (QueryOver is just a wrapper around Criteria, mind you).

    So, for HQL (and SQL), it goes like this:

       1: public static class QueryExtensions
       2: {
       3:     private static readonly PropertyInfo sessionProperty = typeof (QueryImpl).GetProperty("Session", BindingFlags.NonPublic | BindingFlags.Instance);
       4:  
       5:     public static String ToSql(this IQuery query)
       6:     {
       7:         if (query is QueryImpl)
       8:         {
       9:             var session = sessionProperty.GetValue(query, null) as ISession;
      10:             var sessionImpl = session.GetSessionImplementation();
      11:             var translatorFactory = new ASTQueryTranslatorFactory();
      12:             var translators = translatorFactory.CreateQueryTranslators(query.QueryString, null, false, sessionImpl.EnabledFilters, sessionImpl.Factory);
      13:  
      14:             return translators[0].SQLString;
      15:         }
      16:         else if (query is SqlQueryImpl)
      17:         {
      18:             return (query.QueryString);
      19:         }
      20:  
      21:         throw (new NotSupportedException("Query type is not supported."));
      22:     }
      23: }

    You can pass any implementation if IQuery, such as one produced from ISession.CreateQuery() or ISession.CreateSQLQuery(). The static field is merely for performance reasons.

    As for Criteria:

       1: public static class CriteriaExtensions
       2: {
       3:     public static String ToSql(this ICriteria criteria)
       4:     {
       5:         var criteriaImpl = criteria as CriteriaImpl;
       6:         var sessionImpl = criteriaImpl.Session;
       7:         var factory = sessionImpl.Factory;
       8:         var implementors = factory.GetImplementors(criteriaImpl.EntityOrClassName);
       9:         var loader = new CriteriaLoader(factory.GetEntityPersister(implementors[0]) as IOuterJoinLoadable, factory, criteriaImpl, implementors[0], sessionImpl.EnabledFilters);
      10:  
      11:         return loader.SqlString.ToString();
      12:     }
      13: }

    And finally, QueryOver, just a small wrapper around the Criteria version:

       1: public static class QueryOverExtensions
       2: {
       3:     public static String ToSql(this IQueryOver queryOver)
       4:     {
       5:         var criteria = queryOver.UnderlyingCriteria;
       6:         return (criteria.ToSql());
       7:     }
       8: }

    Hope you find this useful! Winking smile

    Read more...

  • Adding Support for ISupportInitialize in NHibernate

    The .NET ISupportInitialize interface is used when we want to support staged initialization for objects. Its BeginInit method is called when initialization is about to start and EndInit when it is finished.

    If we want, it is easy to add support for it in NHibernate. An option would be:

    • BeginInit is called when the object is instantiated, like when NHibernate has loaded a record from the database and is about to hydrate the entity, and immediately after the Id property is set;
    • EndInit is called after all properties are set.

    We do this by using a custom interceptor, like we have in the past. We start by writing a class that inherits from EmptyInterceptor, and implements the listener interface for the PostLoad event, IPostLoadEventListener:

       1: public sealed class SupportInitializeInterceptor : EmptyInterceptor, IPostLoadEventListener
       2: {
       3:     private ISession session = null;
       4:  
       5:     public override void SetSession(ISession session)
       6:     {
       7:         this.session = session;
       8:         base.SetSession(session);
       9:     }
      10:  
      11:     public override Object Instantiate(String clazz, EntityMode entityMode, Object id)
      12:     {
      13:         var listeners = (this.session.SessionFactory as SessionFactoryImpl).EventListeners;
      14:         var metadata = this.session.SessionFactory.GetClassMetadata(clazz);
      15:         var proxy = metadata.Instantiate(id, entityMode);
      16:         var initializable = proxy as ISupportInitialize;
      17:  
      18:         if (initializable != null)
      19:         {
      20:             initializable.BeginInit();
      21:         }
      22:  
      23:         if (listeners.PostLoadEventListeners.OfType<SupportInitializeInterceptor>().Any() == false)
      24:         {
      25:             listeners.PostLoadEventListeners = listeners.PostLoadEventListeners.Concat(new IPostLoadEventListener[] { this }).ToArray();
      26:         }
      27:  
      28:         return (proxy);
      29:     }
      30:  
      31:     #region IPostLoadEventListener Members
      32:  
      33:     void IPostLoadEventListener.OnPostLoad(PostLoadEvent @event)
      34:     {
      35:         var initializable = @event.Entity as ISupportInitialize;
      36:  
      37:         if (initializable != null)
      38:         {
      39:             initializable.EndInit();
      40:         }
      41:     }
      42:  
      43:     #endregion
      44: }
    Then, before creating a session factory, we need to register it in the Configuration instance:
       1: var sessionFactory = cfg.SetInterceptor(new SupportInitializeInterceptor()).BuildSessionFactory();
    Now, if your entity implements ISupportInitialize, NHibernate will automagically call its methods at the proper time. As simple as this! Winking smile

    Read more...

  • Lesser-Known NHibernate Features – Generating Database Scripts

    As you may know, NHibernate knows how to generate the database for you from its model. Any of the supported databases will do.

    What you may not know is that you can simply generate the SQL scripts that would be used to either generate the database from scratch or just update it to match the model as it is. For that you use the SchemaExport and SchemaValidator classes.

    SchemaValidator takes a Configuration instance and basically throws an exception if, when its Validate method is called, the database does not match the model.

    SchemaExport has far more options; it can:

    • Create or drop a database model based on the entity model;
    • Output the SQL to a file, either executing it at the same time or not;
    • Execute the SQL to another arbitrary database connection;
    • Execute a custom action after each line of the generated SQL script.

    An example:

       1: var validator = new SchemaValidator(cfg);
       2:  
       3: try
       4: {
       5:     validator.Validate();
       6: }
       7: catch
       8: {
       9:     var export = new SchemaExport(cfg).SetOutputFile("Script.sql");
      10:  
      11:     //send the script to standard output and execute it
      12:     export.Execute(useStdOut: true, execute: true, justDrop: false);
      13:     //or
      14:     //send all lines of the script to the System.Console.WriteLine method
      15:     export.Execute(scriptAction: System.Console.WriteLine, execute: false, justDrop: false);
      16: }

    Read more...

  • NHibernate Pitfalls: Versioned Entities Are Not Batcheable

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

    This is a problem similar to the one with native id generators. Basically, because there are different versioning strategies – timestamp, counter, native, etc, – NHibernate needs to issue a SELECT after a versioned entity is INSERTEd or UPDATEd. While this wouldn’t be necessary when NHibernate manages the version on the “client side”, like:

       1: UPDATE MyEntity SET Version = 2 WHERE ...;
       2: //or
       3: UPDATE MyEntity SET Version = GETDATE() WHERE ...;

    But not if the version is handled on the database side, like when using SQL Server’s ROWVERSION/TIMESTAMP columns or Oracle’s ORA_ROWSCN pseudo-columns. In these cases, NHibernate needs to issue a SELECT after each INSERT or UPDATE:

       1: UPDATE MyEntity SET ... WHERE ...;
       2: SELECT Version FROM MyEntity WHERE ...;

    This breaks batching, because it needs to be done immediately after each INSERT/UPDATE.

    Read more...

  • Entity Developer Review, Part 4

    Introduction

    This is my fourth post on Entity Developer, Devart’s O/RM tool for NHibernate, Entity Framework and LINQ to SQL. The first post was an introduction to Entity Developer and a general description of its usage, the second was focused on NHibernate and the third on Entity Framework. This time I am going to cover some aspects that were not mentioned in the previous posts.

    Providers

    Entity Developer supports several ADO.NET providers:

    • SQL Server
    • PostgreSQL
    • MySQL
    • Oracle
    • SQLite
    • Firebird
    • DB2

    I noticed that some options, namely, the ability to connect to certain databases or to reverse engineer from them, is only present if a suitable ADO.NET provider is found. The mapping between .NET types and database-specific ones is configurable.

    Editions

    There are several editions of Entity Developer available, some only cover a specific product (Entity Framework, NHibernate or LINQ to SQL) and the Professional one covers them all. There’s also the free Express edition, which has some limitations, namely regarding the number of entities supported (a short number) and the unavailability of custom templates.

    Generation Options

    There are some very cool features available in NHibernate projects, such as being able to select whether an enumeration will be persisted as an integer or as a string, the default collection type (set or bag), default cascade option (odd, delete-orphan is missing), the default identifier generator – with specific options for each included generator that supports them -, access for properties, the default laziness, etc. If required, it will generate classes as partial, with a partial OnCreated method that can be implemented in a separate file, this is very useful to avoid messing with the generated files. The ability to have classes implement INotifyPropertyChanged (also with partial methods) and ICloneable (shallow copy) is also nice, as is the option to add regular serialization and WCF Data Contract attributes. Finally, I also find interesting the possibility to implement validation using one of three validation frameworks: NHibernate Validator, Data Annotations Validation and Enterprise Library Validation Application Block. Supported automatic validations include range, length, mandatory, email, IP address, numeric and regular expression but also NHibernate’s built-in validation mechanism (IValidatable). For NHibernate and Entity Framework projects, it is possible to specify stored procedures for an entity’s basic operations (CRUD) and to map the results of stored procedures to model entities. In general, NHibernate projects offer far more options than the others, because the underlying library also does.

    Support

    The help system (classic Windows Help) is comprehensive and includes both a reference as well as walkthroughs. There is a User Voice page for taking user suggestions (https://devart.uservoice.com/forums/38671-entity-developer) and an online forum (http://forums.devart.com/viewforum.php?f=32) which appears to have some activity.

    Queries

    It is possible to run LINQ and Entity-SQL queries against model entities directly on the application. This can provide a helpful insight on the state of the mappings and is a welcome feature.

    Designer

    The Designer windows can be configured as per the default size (A4, etc), background color, header and footer, orientation, margins, etc. These are mostly used for printing. There’s also a skin mechanism, but I honestly haven’t used it. It is possible to snap to a configurable virtual grid, for a more tidy model. Zooming and coloring the entities differently is supported. Having multiple Designer windows is a must have for large models, and it works well.

    Visual Studio Integration

    The integration with Visual Studio is functional and meets its expectations. I would also like to see an easy option for debugging T4 templates.

    Conclusion

    I enjoyed using Entity Developer, it is one of the few currently available O/RM modeling tools for .NET with a commercial license, which also offers a free edition. It is definitely a possibility to be considered when working with big models, because, for once, it is simply not feasible to reverse engineer tens of database tables by hand. I would like to have command line support (couldn’t find references to it) because it would be helpful for refreshing models and generating SQL or database objects. Other than that, I think the product is very complete and can easily match or even surpass its adversaries.

    Do let me know if there is anything unclear or if you want some more details, but don’t forget that I don’t work or am in any way affiliated with Devart, so I may not be able to help you! Winking smile

    Read more...

  • Lesser-Known NHibernate Features: Validation and Lifecycle Interfaces

    NHibernate offers two interfaces that can be used to validate an entity before it is saved or updated or to cancel its saving, updating and deleting: IValidatable and ILifecycle. They are an alternative to events, and don’t need anything else to work other than be implemented by some entity.

    Here’s what a possible implementation of IValidatable looks like:

       1: public class Product : IValidatable
       2: {
       3:     public String Name { get; set; }
       4:     public Decimal Price { get; set; }
       5:  
       6:     void IValidatable.Validate()
       7:     {   
       8:         if (String.IsNullOrWhitespace(this.Name) == true)
       9:         {
      10:             throw new InvalidOperationException("Name must be set");
      11:         }
      12:  
      13:         if (this.Price <= 0)
      14:         {
      15:             throw new InvalidOperationException("Price needs to be greater than 0");
      16:         }
      17:     }
      18: }

    As you can see, you can cancel the current operation - save or update - by throwing an exception.

    As for ILifecycle, it not only allows us to specifically cancel a save, update and also delete operation, but also to be notified as soon as the entity is loaded:

       1: public class Customer : ILifecycle
       2: {
       3:     public IList<Order> Orders { get; set; }
       4:     public Int32 Id { get; set; }
       5:     public String Name { get; set; }
       6:     
       7:     LifecycleVeto ILifecycle.OnDelete(ISession s)
       8:     {
       9:         return ((this.Orders.Any() == true) ? LifecycleVeto.Veto : LifecycleVeto.NoVeto);
      10:     }
      11:     void ILifecycle.OnLoad(ISession s, Object id)
      12:     {
      13:         Trace.WriteLine(String.Format("A customer with id {0} was loaded", id));
      14:     }
      15:     LifecycleVeto ILifecycle.OnSave(ISession s)
      16:     {
      17:         return ((String.IsNullOrWhitespace(this.Name) == true) ? LifecycleVeto.Veto : LifecycleVeto.NoVeto);
      18:     }
      19:     LifecycleVeto ILifecycle.OnUpdate(ISession s)
      20:     {
      21:         using (var childSession = s.GetSession(s.ActiveEntityMode))
      22:         {
      23:             var any = childSession.CreateQuery("select 1 from Customer where Id != :id and Name = :name").SetParameter("id", this.Id).SetParameter("name", this.Name).List<Int32>();
      24:             return ((any.Count != 0) ? LifecycleVeto.Veto : LifecycleVeto.NoVeto);
      25:         }
      26:     }

    You even have access to the current session.

    This is a classic feature of  NHibernate, but some people don’t like it because it “pollutes” our POCO entities with NHibernate-specific features, which makes our entities less reusable, and forces us to reference the NHibernate DLL. It may, however, come in handy sometimes as a "poor-man's" event system.

    Read more...

  • Entity Developer Review, Part 2

    Here’s my second post on Entity Developer, this time, focused on NHibernate. You can find the first part here.

    I created a new model item of type NHibernate and chose the option to generate from the database:

    image

    Mind you, you need to have the database providers installed for the databases you want to access, Entity Developer does not include them.I was then presented with a list of database objects:

    image

    After I selected a few, Entity Developer shows the class and properties naming rules dialog:

    image

    Next, some more options, pretty complete. Very useful is the option to detect many-to-many associations and table per type inheritances. These will be the default settings, but we can override them on a class by class basis:

    image

    Interesting, the next dialog gives an opportunity to split entities among different diagrams according to the database object’s schema:

    image

    Finally, we get to choose the template that will be used to generate the classes (the only included one is for HBM.XML) and set some of its properties, like, generate a single file or one file per entity, implement standard methods such as Equals or GetHashCode, standard interfaces like NHibernate’s IValidatable, ICloneable and INotifyPropertyChanged, add data contract serialization attributes for WCF and add support for a validation framework (NHibernate Validator, Data Annotations or Enterprise Library Validation Application Block):

    image

    There are several templates available, in both C# and Visual Basic, which we can browse and select (others can be added manually):

    The code is immediately generated, unless there are validation errors in the model, like, a table without primary key:

    image

    In the Model window, selecting a class or a property of a class, we can set its properties, I think all of NHibernate’s features are there, collection types, cascading options, id generators, etc, plus validation settings, which will be translated to the validation framework of choice.

    The HBM.XML files are set as embedded resources, which is also nice, and the Web.config file is updated with the connection string to the selected database. Weird, the dialect was set to MsSql2005Dialect, which doesn’t make much sense since I was connecting to SQL Server 2014. It is possible to select another dialect through the user interface, but dialects and drivers appear as text boxes, not much of a help.

    All in all, it’s pretty impressive, it seems that all NHibernate features are present – did I mention that it is even possible to configure filters? – making Entity Developer a very interesting product. Another strong point is the T4 template system, which, with some effort, allows us to generate code mappings or whatever we want. The only problem I see is that no template for NHibernate's built-in mapping by code is supplied, although one exists for Fluent NHibernate.

    Next, Entity Framework.

    Read more...

  • Entity Developer Review, Part 1

    Introduction

    I recently started to use Entity Developer, by Devart, to generate entities from my databases. It is a commercial product, mind you, and I am in no way affiliated with them, I just happen to like it, so I am going to talk a bit about it.

    A very strong point is that it supports out of the box NHibernate, Entity Framework and the now half-forgotten LINQ to SQL, which makes it stand out from other products. This is not going to be a thorough review, but I will post more as soon as I explore things in more depth.

    Look and Feel

    In general, the UI has a classic Windows appearance, with multiple floating windows, and there are a couple of skins available, but I didn’t pay much attention to it.

    image

    There’s a Database Explorer window which allows us to browse our databases and to see what’s in there (tables, views, functions and stored procedures), plus we can drag objects from it into the Diagram window, which will add this objects to the model.

    The Diagram window allows automatic layout of the objects in it, having each in different colors, adding notes (nice!) and new model items (classes, inheritances, associations, enumerations. A diagram can be “stamped” with the author’s details (name, company, version, date, etc), which is good if we are to print it or generate a bitmap from it (supported natively). It can be zoomed and there’s a Diagram Overview window that shows the full model at once, so that we can easily spot objects outside of the visible area.

    There may be several diagrams for an entity model, the core of an Entity Developer project, and this model has it’s own window, on which we can explore it and see all the mapped database objects and corresponding model items, including inheritances, associations, components (complex/value types), etc. We also have there the list of templates available for the current project type.

    There’s the possibility to generate a SQL script from the model, but in NHibernate projects, only databases SQL Server, SQL Server Compact Edition, Oracle, MySQL and PostgreSQL, this requires that the proper .NET providers are present. For Entity Framework projects, I could only find the option to generate the script for SQL Server, and, of course, LINQ to SQL only supports SQL Server as well. There’s an option for updating the model from the database as well, in case we chose to generate it from the database.

    It is of course possible to validate the model, and the Error List window will present all outcomes of this validation, which can either be errors or warnings. A nice thing: double clicking on a notification, we jump directly to the model item that caused it. It would be interesting as well to have the option to quick fix the problem, but I reckon it’s not always possible or easy to do in an automated fashion.

    When it comes to actually generating the code, there are an endless number of options, from capitalization of properties, lazy loading of associations, inclusion of foreign keys, etc. These settings are of course dependent on the project (NHibernate, Entity Framework or LINQ to SQL), because not all libraries have the same features. The generation is based on T4 templates, which is nice, because they are a standard in .NET. Only one template for each API is include, but it is very easy to write our own, by copying from an existing one and modifying it to our liking. I have yet to find a T4 debugger, Entity Developer, unsurprisingly, does not offer one.

    Conclusion

    OK, so far I have talked in general about Entity Developer, in my next posts, I will talk about NHibernate and Entity Framework specifics and also about advanced functionality.

    Read more...