Contents tagged with Extensibility

  • 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...

  • Registering SQL Server Built-in Functions to Entity Framework Code First

    It is possible to register custom functions that exist in the database so that they can be called by Entity Framework Code First LINQ queries.

    For example, consider the SOUNDEX function (yes, I know, I know, I always give SOUNDEX as an example for LINQ extensions! Winking smile). We could write it in C# as this:

       1: public static String Soundex(this String input)
       2: {
       3:     const String values = "01230120022455012623010202";
       4:     const Int32 encodingLength = 4;
       5:  
       6:     var prevChar = ' ';
       7:  
       8:     input = Normalize(input);
       9:  
      10:     if (input.Length == 0)
      11:     {
      12:         return (input);
      13:     }
      14:  
      15:     var builder = new StringBuilder(input[0]);
      16:  
      17:     for (var i = 1; ((i < input.Length) && (builder.Length < encodingLength)); ++i)
      18:     {
      19:         var c = values[input[i] - 'A'];
      20:  
      21:         if ((c != '0') && (c != prevChar))
      22:         {
      23:             builder.Append(c);
      24:             prevChar = c;
      25:         }
      26:     }
      27:  
      28:     while (builder.Length < encodingLength)
      29:     {
      30:         builder.Append('0');
      31:     }
      32:  
      33:     return (builder.ToString());
      34: }
      35:  
      36: private static String Normalize(String text)
      37: {
      38:     var builder = new StringBuilder();
      39:  
      40:     foreach (var c in text)
      41:     {
      42:         if (Char.IsLetter(c) == true)
      43:         {
      44:             builder.Append(Char.ToUpper(c));
      45:         }
      46:     }
      47:  
      48:     return (builder.ToString());
      49: }

    If we want this method to be callable by a LINQ query, we need to add the DbFunctionAttribute to it, specifying the name of the database function we wish to call, because the .NET method and the database function names can be different:

       1: [DbFunction("SqlServer", "SOUNDEX")]
       2: public static String Soundex(this String input)
       3: {
       4:     //...
       5: }

    And for calling it:

       1: var soundexNames = ctx.Projects.Select(p => p.Name.Soundex()).ToList();

    However, for certain database functions, it requires a bit more work to get done. Let us consider now the FORMAT function and a .NET implementation:

       1: public static String Format(this DateTime value, String format, String culture)
       2: {
       3:     return (value.ToString(format, CultureInfo.CreateSpecificCulture(culture)));
       4: }

    Besides adding the DbFunctionAttribute attribute:

       1: [DbFunction("CodeFirstDatabaseSchema", "FORMAT")]
       2: public static String Format(this DateTime value, String format, String culture)
       3: {
       4:     //...
       5: }

    it also requires that we register it explicitly in our model, for that, we override the OnModelCreating method and add a custom convention:

       1: protected override void OnModelCreating(DbModelBuilder modelBuilder)
       2: {
       3:     modelBuilder.Conventions.Add(new RegisterFunctionConvention());
       4:  
       5:     base.OnModelCreating(modelBuilder);
       6: }

    The convention being:

       1: public class RegisterFunctionConvention : IStoreModelConvention<EdmModel>
       2: {
       3:     public void Apply(EdmModel item, DbModel model)
       4:     {
       5:         var valueParameter = FunctionParameter.Create("value", this.GetStorePrimitiveType(model, PrimitiveTypeKind.DateTime), ParameterMode.In);
       6:         var formatParameter = FunctionParameter.Create("format", this.GetStorePrimitiveType(model, PrimitiveTypeKind.String), ParameterMode.In);
       7:         var cultureParameter = FunctionParameter.Create("culture", this.GetStorePrimitiveType(model, PrimitiveTypeKind.String), ParameterMode.In);
       8:         var returnValue = FunctionParameter.Create("result", this.GetStorePrimitiveType(model, PrimitiveTypeKind.String), ParameterMode.ReturnValue);
       9:  
      10:         var function = this.CreateAndAddFunction(item, "FORMAT", new[] { valueParameter, formatParameter, cultureParameter }, new[] { returnValue });
      11:     }
      12:  
      13:     protected EdmFunction CreateAndAddFunction(EdmModel item, String name, IList<FunctionParameter> parameters, IList<FunctionParameter> returnValues)
      14:     {
      15:         var payload = new EdmFunctionPayload { StoreFunctionName = name, Parameters = parameters, ReturnParameters = returnValues, Schema = this.GetDefaultSchema(item), IsBuiltIn = true };
      16:         var function = EdmFunction.Create(name, this.GetDefaultNamespace(item), item.DataSpace, payload, null);
      17:  
      18:         item.AddItem(function);
      19:  
      20:         return (function);
      21:     }
      22:  
      23:     protected EdmType GetStorePrimitiveType(DbModel model, PrimitiveTypeKind typeKind)
      24:     {
      25:         return (model.ProviderManifest.GetStoreType(TypeUsage.CreateDefaultTypeUsage(PrimitiveType.GetEdmPrimitiveType(typeKind))).EdmType);
      26:     }
      27:  
      28:     protected String GetDefaultNamespace(EdmModel layerModel)
      29:     {
      30:         return (layerModel.GlobalItems.OfType<EdmType>().Select(t => t.NamespaceName).Distinct().Single());
      31:     }
      32:  
      33:     protected String GetDefaultSchema(EdmModel layerModel)
      34:     {
      35:         return (layerModel.Container.EntitySets.Select(s => s.Schema).Distinct().SingleOrDefault());
      36:     }
      37: }

    I got some of the metadata code from Diego Vega’s (@divega) repository: https://github.com/divega/, but changed it slightly.

    Now we have the FORMAT function available to LINQ:

       1: var projectDates = ctx.Projects.Select(p => p.Start.Format("D", "pt-PT")).ToList();

    Now, I hear you ask: why for SOUNDEX we just need to add a simple attribute and for FORMAT we need so much more? Well, it just happens that SOUNDEX is defined in the Entity Framework SQL Server provider manifest - see it here. All of the functions in SqlFunctions are present in the manifest, but the opposite is not true - not all functions in the manifest are in SqlFunctions, but that's the way it is! Thanks to @divega for the explanation.

    Some things worth mentioning:

    • The namespace and name used in the DbFunctionAttribute attribute must match those passed to EdmFunction.Create (CodeFirstDatabaseSchema is what GetDefaultNamespace returns;
    • You cannot specify two functions with the same name and different parameters.

    There is an open request to add the FORMAT function to the list of functions supported out of the box by Entity Framework Code First: https://entityframework.codeplex.com/workitem/2586 through the SqlFunctions class, but in the meantime, this might be useful!

    Read more...

  • ASP.NET Web Forms Extensibility: Output Encoders

    Since version 4, ASP.NET offers an extensible mechanism for encoding the output. This is the content that will be returned to the browser. I already refered it in Providers.

    A base class exists, HttpEncoder, for which it used to be the default implementation. It has the responsibility to encode all contents sent to the server, in a differentiated manner – JavaScript is encoded in a way, HTML in another, URLs in another, and so on. Since ASP.NET 4.5, the default implementation is AntiXssEncoder. Those familiar with Anti-Cross Site Scripting Library (now Web Protection Library) will recognize this class, which offers better protection against cross site scripting attacks.

    This class offers a number of virtual methods that you can override to change the default behavior: HeaderNameValueEncode (for encoding headers sent in the response), HtmlAttributeEncode (for tag attributes), HtmlEncode (for generic text content), JavaScriptStringEncode (for JavaScript), UrlEncode (URLs) and UrlPathEncode (URL parts). Do create a dummy encoder and debug through these methods to see what they are called with.

    The actual implementation to use can be configured by code or XML configuration (the Web.config file).

    For using code configuration, one has to change the HttpEncoder.Current in at most the Application_Start event, after that it will be too late:

       1: protected void Application_Start()
       2: {
       3:     HttpEncoder.Current = new MyEncoder();
       4: }

    The default implementation is always available in the read only property HttpEncoder.Default.

    If you prefer to change the Web.config file, you need to set the encoderType attribute of the httpRuntime section:

       1: <httpRuntime encoderType="MyEncoder, MyAssembly"/>

    It is a nice addition, especially together with the validation provider model introduced with ASP.NET 4, which will be the topic of my next post on ASP.NET Web Forms extensibility.

    Read more...

  • Getting the SQL from a LINQ Query in NHibernate

    In case you ever want to have a look at the generated SQL before it is actually executed, you can use this extension method:

       1: public static String ToSql(this IQueryable queryable)
       2: {
       3:     var sessionProperty = typeof(DefaultQueryProvider).GetProperty("Session", BindingFlags.NonPublic | BindingFlags.Instance);
       4:     var session = sessionProperty.GetValue(queryable.Provider, null) as ISession;
       5:     var sessionImpl = session.GetSessionImplementation();
       6:     var factory = sessionImpl.Factory;
       7:     var nhLinqExpression = new NhLinqExpression(queryable.Expression, factory);
       8:     var translatorFactory = new ASTQueryTranslatorFactory();
       9:     var translator = translatorFactory.CreateQueryTranslators(nhLinqExpression, null, false, sessionImpl.EnabledFilters, factory).First();
      10:     //in case you want the parameters as well
      11:     //var parameters = nhLinqExpression.ParameterValuesByName.ToDictionary(x => x.Key, x => x.Value.Item1);
      12:  
      13:     return translator.SQLString;
      14: }

    Just call it on an IQueryable or IQueryable<T> instance, such as the one you got from ISession.Query<T>:

       1: var query = session.Query<Product>().Where(p => p.Price > 100);
       2: var sql = query.ToSql();

    Parameters such as 100 will be located in the nhLinqExpression.ParameterValuesByName collection.

    Read more...

  • NHibernate Pitfalls: Refreshing Manually Created Entities Does Not Bring Lazy Properties of Base Types

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

    Suppose you have some properties of an entity, including its id, and you want to refresh its state from the database:

       1: var product = new Product { ProductId = 1 };
       2:  
       3: //product.Image is null
       4:  
       5: session.Refresh(product);
       6:  
       7: //product.Image is null

    Image is a Byte[] and is configured as lazy. The problem is that NHibernate is not capable of returning a proxy for it, because the entity itself is not a proxy.

    This does not happen for associated entities (one-to-one, many-to-one, one-to-many and many-to-many):

       1: var order = new Order { OrderId = 1 };
       2:  
       3: //order.Customer is null
       4:  
       5: session.Refresh(order);
       6:  
       7: //order.Customer is a proxy and accessing the property will load it

    In this case, Customer is another entity, and NHibernate can assign the Order.Customer property a proxy to it.

    Because of this problem, I created a simple extension method that loads all properties. It is even smart enough to use proxies, if we so require it:

       1: public static void InitializeLazyProperties(this ISession session, Object entity, Boolean useProxyWhenPossible = true)
       2: {
       3:     if (entity.IsProxy() == true)
       4:     {
       5:         //if entity is a proxy, use the default mechanism
       6:         NHibernateUtil.Initialize(entity);
       7:     }
       8:     else
       9:     {
      10:         var metadata = session.SessionFactory.GetClassMetadata(entity.GetType());
      11:         var propertiesToLoad = new List<String>();
      12:  
      13:         for (var i = 0; i < metadata.PropertyNames.Length; ++i)
      14:         {
      15:             if (metadata.GetPropertyValue(entity, metadata.PropertyNames[i], session.ActiveEntityMode) == null)
      16:             {
      17:                 if ((metadata.PropertyTypes[i].IsEntityType == false) || (useProxyWhenPossible == false))
      18:                 {
      19:                     //either load the value
      20:                     propertiesToLoad.Add(metadata.PropertyNames[i]);
      21:                 }
      22:                 else
      23:                 {
      24:                     //or the id of the associated entity
      25:                     propertiesToLoad.Add(String.Concat(metadata.PropertyNames[i], ".id"));
      26:                 }
      27:             }
      28:         }
      29:  
      30:         var hql = new StringBuilder();
      31:         hql.Append("select ");
      32:         hql.Append(String.Join(", ", propertiesToLoad));
      33:         hql.AppendFormat(" from {0} where id = :id", entity.GetType());
      34:  
      35:         var query = session.CreateQuery(hql.ToString());
      36:         query.SetParameter("id", metadata.GetIdentifier(entity, session.ActiveEntityMode));
      37:  
      38:         var result = query.UniqueResult();
      39:         var values = result as Object[] ?? new Object[] { result };
      40:  
      41:         for (var i = 0; i < propertiesToLoad.Count; ++i)
      42:         {
      43:             var parts = propertiesToLoad[i].Split('.');
      44:             var value = values[i];
      45:             var propertyName = parts.First();
      46:  
      47:             if (parts.Length > 0)
      48:             {
      49:                 var propertyIndex = Array.IndexOf(metadata.PropertyNames, propertyName);
      50:                 var propertyType = metadata.PropertyTypes[propertyIndex].ReturnedClass;
      51:  
      52:                 //create a proxy
      53:                 value = session.Load(propertyType, values[i]);
      54:             }
      55:  
      56:             metadata.SetPropertyValue(entity, propertyName, value, session.ActiveEntityMode);
      57:         }
      58:     }
      59: }

    Of course, it requires that at leat the id property is set. It can be used as:

       1: var order = new Order { OrderId = 360448 };
       2:  
       3: session.InitializeLazyProperties(order);

    Have fun! Winking smile

    Read more...

  • ASP.NET Web Forms Extensibility: Page Parser Filters

    Introduction

    ASP.NET includes a valuable yet not well known extension point called the page parser filter. I once briefly talked about it in the context of SharePoint, but I feel a more detailed explanation is in order.

    A page parser filter is a class with a public parameterless constructor that inherits from PageParserFilter and is registered on the Web.config file, in the pages section, pageParserFilterType attribute. It is called when ASP.NET is compiling a page, the first time it is called, for every page. There can be only one page parser filter per web application.

    Parser

    Why is it a parser? Well, it parses – or, better, receives a notification for - every control declared on the markup of a page (those with runat=”server” or contained inside of), as well as all of the page’s directives (<%@ … %>). The control declarations include all of its attributes and properties, the recognized control type and any complex properties that the markup contains. This allows us to do all kinds of crazy stuff:

    • Inspect, add and remove page directives;
    • Setting the page’s compilation mode;
    • Insert or remove controls or text literals dynamically at specific places;
    • Add/change/remove a control’s properties or attributes;
    • Even (with some reflection magic) change a control’s type or tag.

    So, how do we all this? First, the parser part. We can inspect all page directives by overriding the PreprocessDirective method. This is called for all page directives:

       1: public override void PreprocessDirective(String directiveName, IDictionary attributes)
       2: {
       3:     if (directiveName == "page")
       4:     {
       5:         //make a page asynchronous
       6:         attributes["async"] = "true";
       7:     }
       8:  
       9:     base.PreprocessDirective(directiveName, attributes);
      10: }

    The page’s compilation mode is controlled by GetCompilationMode:

       1: public override CompilationMode GetCompilationMode(CompilationMode current)
       2: {
       3:     return (base.GetCompilationMode(current));
       4: }

    As for adding controls dynamically, we make use of the ParseComplete method:

       1: public override void ParseComplete(ControlBuilder rootBuilder)
       2: {
       3:     if (rootBuilder is FileLevelPageControlBuilder)
       4:     {
       5:         this.ProcessControlBuilder(rootBuilder);
       6:     }
       7:  
       8:     base.ParseComplete(rootBuilder);
       9: }
      10:  
      11: private void ProcessControlBuilder(ControlBuilder builder)
      12: {
      13:     this.ProcessControlBuilderChildren(builder);
      14:  
      15:     if (builder.ControlType == typeof(HtmlForm))
      16:     {
      17:         //add a Literal control inside the form tag
      18:         var literal = ControlBuilder.CreateBuilderFromType(null, builder, typeof(Literal), "asp:Literal", "literal", new Hashtable { { "Text", "Inserted dynamically I" } }, -1, null);
      19:         builder.AppendSubBuilder(literal);
      20:  
      21:         //add an HTML snippet inside the form tag
      22:         builder.AppendLiteralString("<div>Inserted dynamically II</div>");
      23:     }
      24: }
      25:  
      26: private void ProcessControlBuilderChildren(ControlBuilder parentBuilder)
      27: {
      28:     foreach (var builder in parentBuilder.SubBuilders.OfType<ControlBuilder>())
      29:     {
      30:         this.ProcessControlBuilderChildren(builder);
      31:     }
      32: }

    Same for changing a control’s properties:

       1: private static readonly FieldInfo simplePropertyEntriesField = typeof(ControlBuilder).GetField("_simplePropertyEntries", BindingFlags.Instance | BindingFlags.NonPublic);
       2:  
       3: private void SetControlProperty(ControlBuilder builder, String propertyName, String propertyValue)
       4: {
       5:     var properties = (simplePropertyEntriesField.GetValue(builder) as IEnumerable);
       6:  
       7:     if (properties == null)
       8:     {
       9:         properties = new ArrayList();
      10:         simplePropertyEntriesField.SetValue(builder, properties);
      11:     }
      12:  
      13:     var entry = properties.OfType<SimplePropertyEntry>().SingleOrDefault(x => x.Name == propertyName) ?? simplePropertyEntryConstructor.Invoke(null) as SimplePropertyEntry;
      14:     entry.Name = propertyName;
      15:     entry.UseSetAttribute = (builder.ControlType != null && builder.ControlType.GetProperties().Any(x => x.Name.Equals(propertyName, StringComparison.OrdinalIgnoreCase)) == false);
      16:     entry.PersistedValue = propertyValue;
      17:     entry.Value = entry.PersistedValue;
      18:     entry.Filter = String.Empty;
      19:  
      20:     if (properties.OfType<SimplePropertyEntry>().Any(x => x.Name == propertyName) == false)
      21:     {
      22:         (properties as ArrayList).Add(entry);
      23:     }
      24: }
      25:  
      26: private void ProcessControlBuilder(ControlBuilder builder)
      27: {
      28:     if (typeof(IEditableTextControl).IsAssignableFrom(builder.ControlType) == true)
      29:     {
      30:         this.SetControlProperty(builder, "Text", "Injected dynamically!");
      31:     }
      32:  
      33:     this.ProcessControlBuilderChildren(builder);
      34: }

    And even changing the control’s output tag or instance type:

       1: private static readonly FieldInfo controlTypeField = typeof(ControlBuilder).GetField("_controlType", BindingFlags.Instance | BindingFlags.NonPublic);
       2: private static readonly FieldInfo tagNameField = typeof(ControlBuilder).GetField("_tagName", BindingFlags.Instance | BindingFlags.NonPublic);
       3:  
       4: private void SetControlType(ControlBuilder builder, Type controlType)
       5: {
       6:     controlTypeField.SetValue(builder, controlType);
       7: }
       8:  
       9: private void SetTagName(ControlBuilder controlBuilder, String tagName)
      10: {
      11:     tagNameField.SetValue(controlBuilder, tagName);
      12: }
      13:  
      14: private void ProcessControlBuilder(ControlBuilder builder)
      15: {
      16:     if (builder.TagName != null)
      17:     {
      18:         this.SetTagName(builder, builder.TagName.ToUpper());
      19:     }
      20:  
      21:     if (builder.ControlType == typeof(MyControl))
      22:     {
      23:         this.SetControlType(builder, typeof(MyDerivedControl));
      24:     }
      25:  
      26:     this.ProcessControlBuilderChildren(builder);
      27: }

    Why would we want to change a control’s type? Well, thing about generics, for once.

    Filter

    And now the filtering part: why is it a filter? Because it allows us to filter and control a number of things:

    • The allowed master page, base page class and source file;
    • The allowed controls;
    • The total number of controls allowed on a page;
    • The total number of direct and otherwise references on a page;
    • Allow or disallow code and event handler declarations;
    • Allow or disallow code blocks (<%= … %>, <%: … %>, <% … %>);
    • Allow or disallow server-side script tags (<script runat=”server”>…</script>);
    • Allow, disallow and change data binding expressions (<%# … %>);
    • Add, change or remove event handler declarations.

    All of the filtering methods and properties described below return a Boolean flag and its base implementation may or may not be called, depending on the logic that we want to impose.

    Allowing or disallowing a base page class is controlled by the AllowBaseType method (the default is to accept):

       1: public override Boolean AllowBaseType(Type baseType)
       2: {
       3:     return (baseType == typeof(MyBasePage));
       4: }

    For master pages, user controls or source files we have the AllowVirtualReference virtual method (again, the default is true):

       1: public override Boolean AllowVirtualReference(String referenceVirtualPath, VirtualReferenceType referenceType)
       2: {
       3:     if (referenceType == VirtualReferenceType.Master)
       4:     {
       5:         return (referenceVirtualPath == "AllowedMaster.Master");
       6:     }
       7:     else if (referenceType == VirtualReferenceType.UserControl)
       8:     {
       9:         return (referenceVirtualPath != "ForbiddenControl.ascx");
      10:     }
      11:  
      12:     return (base.AllowVirtualReference(referenceVirtualPath, referenceType));
      13: }

    Controls are controlled (pun intended) by AllowControl, which also defaults to accept:

       1: public override Boolean AllowControl(Type controlType, ControlBuilder builder)
       2: {
       3:     return (typeof(IForbiddenInterface).IsAssignableFrom(controlType) == false);
       4: }

    This may come in handy to disallow the usage of controls in ASP.NET MVC ASPX views!

    The number of controls and dependencies on a page is defined by NumberOfControlsAllowed, NumberOfDirectDependenciesAllowed and TotalNumberOfDependenciesAllowed. Interesting, the default for all these properties is 0, so we have to return –1:

       1: public override Int32 NumberOfControlsAllowed
       2: {
       3:     get
       4:     {
       5:         return (-1);
       6:     }
       7: }
       8:  
       9: public override Int32 NumberOfDirectDependenciesAllowed
      10: {
      11:     get
      12:     {
      13:         return (-1);
      14:     }
      15: }
      16:  
      17: public override Int32 TotalNumberOfDependenciesAllowed
      18: {
      19:     get
      20:     {
      21:         return (-1);
      22:     }
      23: }

    Direct dependencies are user controls directly declared in the page and indirect ones are those declared inside other user controls.

    Code itself, including event handler declarations, are controlled by AllowCode (default is true):

       1: public override Boolean AllowCode
       2: {
       3:     get
       4:     {
       5:         return (true);
       6:     }
       7: }

    If we want to change a data binding expression, we resort to ProcessDataBindingAttribute, which also returns true by default:

       1: public override Boolean ProcessDataBindingAttribute(String controlId, String name, String value)
       2: {
       3:     if (name == "Text")
       4:     {
       5:         //Do not allow binding the Text property
       6:         return (false);
       7:     }
       8:  
       9:     return (base.ProcessDataBindingAttribute(controlId, name, value));
      10: }

    For intercepting event handlers, there’s the ProcessEventHook, which likewise returns true by default:

       1: public override Boolean ProcessEventHookup(String controlId, String eventName, String handlerName)
       2: {
       3:     if (eventName == "SelectedIndexChanged")
       4:     {
       5:         //Remove event handlers for the SelectedIndexChanged event
       6:         return (false);
       7:     }
       8:  
       9:     return (base.ProcessEventHookup(controlId, eventName, handlerName));
      10: }

    And finally, for code blocks, server-side scripts and data binding expressions, there’s the ProcessCodeConstruct method, which likewise also allows everything by default:

    Conclusion

    This was in no means an in-depth description of page parser filters, I just meant to give you an idea of its (high) potential. It is very useful to restrict what end users can place on their pages (SharePoint style) as well as for adding dynamic control programmatically in specific locations of the page, before it is actually built.

    As usual, let me hear your thoughts! Winking smile

    Read more...

  • Making Better Use of the NHibernate HiLo Generator

    Introduction

    NHibernate’s HiLo (High-Low) id generation algorithm is one of the most commonly used, and for good reasons:

    • It is database-independent, that is, does not rely on any database-specific functionality such as SQL Server’s IDENTITY and Oracle’s SEQUENCE;
    • It allows batching of inserts;
    • It complies with the Unit of Work pattern, because it sends all writes at the same time (when the session is flushed);
    • Your code does not need to know or care about it.

    Now, this post does not intent to explain this algorithm in depth, for that I recommend the NHibernate HiLo Identity Generator article or Choosing a Primary Key: Natural or Surrogate?, for a more in-depth discussion of id generation strategies. Here I will talk about how to make better use of the NHibernate implementation.

    Max Low

    First of all, you can configure the max low value for the algorithm, using by code mapping, like this:

       1: x.Generator(Generators.HighLow, g => g.Params(new { max_lo = 100 }));

    The default max low value is 32767. When choosing a lower or a higher value, you should take into consideration:

    • The next high value is updated whenever a new session factory is created, or the current low reaches the max low value;
    • If you have a big number of inserts, it might pay off to have a higher max low, because NHibernate won’t have to go to the database when the current range is exhausted;
    • If the session factory is frequently restarted, a lower value will prevent gaps.

    There is no magical number, you will need to find the one that best suits your needs.

    One Value for All Entities

    With the default configuration of HiLo, a single table, row and column will be used to store the next high value for all entities using HiLo. The by code configuration is as follows:

       1: this.Id(x => x.SomeId, x =>
       2: {
       3:     x.Column("some_id");
       4:     x.Generator(Generators.HighLow);
       5: });

    The default table is called HIBERNATE_UNIQUE_KEY, and its schema is very simple:

    image

    Whenever NHibernate wants to obtain and increment the current next high value, it will issue SQL like this (for SQL Server):

       1: -- select current value
       2: select next_hi
       3: from hibernate_unique_key with (updlock, rowlock)
       4:  
       5: -- update current value
       6: update hibernate_unique_key
       7: set next_hi = @p0
       8: where next_hi = @p1;

    There are pros and cons to this default approach:

    • Each record will have a different id, there will never be two entities with the same id;
    • Because of the sharing between all entities, the ids will grow much faster;
    • When used simultaneously by several applications, there will be some contention on the table, because it is being locked whenever the next high value is obtained and incremented;
    • The HIBERNATE_UNIQUE_KEY table is managed automatically by NHibernate (created, dropped and populated).

    One Row Per Entity

    Another option to consider, which is supported by NHibernate’s HiLo generator, consists of having each entity storing its next high value in a different row. You achieve this by supplying a where parameter to the generator:

       1: this.Id(x => x.SomeId, x =>
       2: {
       3:     x.Column("some_id");
       4:     x.Generator(Generators.HighLow, g => g.Params(new { where = "entity_type = 'some_entity'" }));
       5: });

    In it, you would specify a restriction on an additional column. The problem is, NHibernate knows nothing about this other column, so it won’t create it.

    One way to go around this is by using an auxiliary database object (maybe a topic for another post). This is a standard NHibernate functionality that allows registering SQL to be executed when the database schema is created, updated or dropped. Using mapping by code, it is applied like this:

       1: private static IAuxiliaryDatabaseObject OneHiLoRowPerEntityScript(Configuration cfg, String columnName, String columnValue)
       2: {
       3:     var dialect = Activator.CreateInstance(Type.GetType(cfg.GetProperty(NHibernate.Cfg.Environment.Dialect))) as Dialect;
       4:     var script = new StringBuilder();
       5:  
       6:     script.AppendFormat("ALTER TABLE {0} {1} {2} {3} NULL;\n{4}\nINSERT INTO {0} ({5}, {2}) VALUES (1, '{6}');\n{4}\n", TableHiLoGenerator.DefaultTableName, dialect.AddColumnString, columnName, dialect.GetTypeName(SqlTypeFactory.GetAnsiString(100)), (dialect.SupportsSqlBatches == true ? "GO" : String.Empty), TableHiLoGenerator.DefaultColumnName, columnValue);
       7:  
       8:     return (new SimpleAuxiliaryDatabaseObject(script.ToString(), null));
       9: }
      10:  
      11: Configuration cfg = ...;
      12: cfg.AddAuxiliaryDatabaseObject(OneHiLoRowPerEntityScript(cfg, "entity_type", "some_entity"));

    Keep in mind that this needs to go before the session factory is built. Basically, we are creating a SQL ALTER TABLE followed by an INSERT statement that change the default HiLo table and add another column that will serve as the discriminator. For making it cross-database, I used the registered Dialect class.

    Its schema will then look like this:

    image

    When NHibernate needs the next high value, this is what it does:

       1: -- select current value
       2: select next_hi
       3: from hibernate_unique_key with (updlock, rowlock)
       4: where entity_type = 'some_entity'
       5:  
       6: -- update current value
       7: update hibernate_unique_key
       8: set next_hi = @p0
       9: where next_hi = @p1
      10: and entity_type = 'some_entity';

    This approach only has advantages:

    • The HiLo table is still managed by NHibernate;
    • You have different id generators per entity (of course, you can still combine multiple entities under the same where clause), which will make them grow more slowly;
    • No contention occurs, because each entity is using its own record on the HIBERNATE_UNIQUE_KEY table.

    One Column Per Entity

    Yet another option is to have each entity using its own column for storing the high value. For that, we need to use the column parameter:

       1: this.Id(x => x.SomeId, x =>
       2: {
       3:     x.Column("some_id");
       4:     x.Generator(Generators.HighLow, g => g.Params(new { column = "some_column_id" }));
       5: });

    Like in the previous option, NHibernate does not know and therefore does not create this new column automatically. For that, we resort to another auxiliary database object:

       1: private static IAuxiliaryDatabaseObject OneHiLoColumnPerEntityScript(Configuration cfg, String columnName)
       2: {
       3:     var dialect = Activator.CreateInstance(Type.GetType(cfg.GetProperty(NHibernate.Cfg.Environment.Dialect))) as Dialect;
       4:     var script = new StringBuilder();
       5:  
       6:     script.AppendFormat("ALTER TABLE {0} {1} {2} {3} NULL;\n{4}\nUPDATE {0} SET {2} = 1;\n{4}\n", TableHiLoGenerator.DefaultTableName, dialect.AddColumnString, columnName, dialect.GetTypeName(SqlTypeFactory.Int32), (dialect.SupportsSqlBatches == true ? "GO" : String.Empty));
       7:  
       8:     return (new SimpleAuxiliaryDatabaseObject(script.ToString(), null));
       9: }
      10:  
      11: Configuration cfg = ...;
      12: cfg.AddAuxiliaryDatabaseObject(OneHiLoColumnPerEntityScript(cfg, "some_column_id"));

    The schema, with an additional column, would look like this:

    image

    And NHibernate executes this SQL for getting/updating the next high value:

       1: -- select current value
       2: select some_column_hi
       3: from hibernate_unique_key with (updlock, rowlock)
       4:  
       5: -- update current value
       6: update hibernate_unique_key
       7: set some_column_hi = @p0
       8: where some_column_hi = @p1;

    The only advantage in this model is to have separate ids per entity, contention on the HiLo table will still occur.

    One Table Per Entity

    The final option to consider is having a separate table per entity (or group of entities). For that, we use the table parameter:

       1: this.Id(x => x.SomeId, x =>
       2: {
       3:     x.Column("some_id");
       4:     x.Generator(Generators.HighLow, g => g.Params(new { table = "some_entity_unique_key" }));
       5: });

    In this case, NHibernate generates the new HiLo table for us, together with the default HIBERNATE_UNIQUE_KEY, if any entity uses it, with exactly the same schema:

    image

    And the SQL is, of course, also identical, except for the table name:

       1: -- select current value
       2: select next_hi
       3: from some_entity_unique_key with (updlock, rowlock)
       4:  
       5: -- update current value
       6: update some_entity_unique_key
       7: set next_hi = @p0
       8: where next_hi = @p1;

    Again, all pros and no cons:

    • Table still fully managed by NHibernate;
    • Different ids per entity or group of entities means they will grow slower;
    • Contention will only occur if more than one entity uses the same HiLo table.

    Conclusion

    As you can see, NHibernate is full of extensibility points. Even when it does not offer out of the box what we need, we usually have a way around it.

    Let me hear from you!

    Read more...

  • NHibernate Connection Resiliency

    Entity Framework 6 included a feature known as connection resiliency. Basically, what it says is, when EF is trying to connect to a database, it will try a number of times before giving up. After each unsuccessful attempt, it will wait some time and then try again. As you can imagine, this is very useful, especially when we are dealing with cloud storage.

    NHibernate does not natively offer this, however, because it is highly extensible, it isn’t too hard to build one such mechanism, which is what I did.

    The code is below, as you can see, it consists of a custom implementation of DriverConnectionProvider, the component of NHibernate that opens connections for us.

       1: public class ResilientDriverConnectionProvider : DriverConnectionProvider
       2: {
       3:     public const String ConnectionDelayBetweenTries = "connection.delay_between_tries";
       4:     public const String ConnectionMaxTries = "connection.max_tries";
       5:  
       6:     private static readonly IInternalLogger log = LoggerProvider.LoggerFor(typeof(ResilientDriverConnectionProvider));
       7:  
       8:     public ResilientDriverConnectionProvider()
       9:     {
      10:         this.MaxTries = 3;
      11:         this.DelayBetweenTries = TimeSpan.FromSeconds(5);
      12:     }
      13:  
      14:     public Int32 MaxTries { get; set; }
      15:  
      16:     public TimeSpan DelayBetweenTries { get; set; }
      17:  
      18:     public override void Configure(IDictionary<String, String> settings)
      19:     {
      20:         String maxTries;
      21:         String delayBetweenTries;
      22:  
      23:         if (settings.TryGetValue(ConnectionMaxTries, out maxTries) == true)
      24:         {
      25:             this.MaxTries = Int32.Parse(maxTries);
      26:         }
      27:  
      28:         if (settings.TryGetValue(ConnectionDelayBetweenTries, out delayBetweenTries) == true)
      29:         {
      30:             this.DelayBetweenTries = TimeSpan.Parse(delayBetweenTries);
      31:         }
      32:  
      33:         base.Configure(settings);
      34:     }
      35:  
      36:     public override IDbConnection GetConnection()
      37:     {
      38:         IDbConnection con = null;
      39:  
      40:         for (var i = 0; i < this.MaxTries; ++i)
      41:         {
      42:             try
      43:             {
      44:                 log.Debug(String.Format("Attempting to get connection, {0} of {1}", (i + 1), this.MaxTries));
      45:                 con = base.GetConnection();
      46:                 log.Debug(String.Format("Got a connection after {0} tries", (i + 1)));
      47:  
      48:                 break;
      49:             }
      50:             catch(Exception ex)
      51:             {
      52:                 if (i == this.MaxTries - 1)
      53:                 {
      54:                     log.Error(String.Format("Could not get connection after {0} tries", this.MaxTries), ex);
      55:                     throw;
      56:                 }
      57:                 else
      58:                 {
      59:                     Thread.Sleep(this.DelayBetweenTries);
      60:                 }
      61:             }
      62:         }
      63:  
      64:         return (con);
      65:     }
      66: }

    The code wraps the attempt to open a connection and retries it a number of times, with some delay in between.

    The way to configure this, in fluent configuration, would be:

       1: var cfg = new Configuration()
       2:     .DataBaseIntegration(
       3:     db =>
       4:     {
       5:         db.ConnectionProvider<ResilientDriverConnectionProvider>();
       6:         //...
       7:     });

    Or if you prefer to use string properties, in either XML or fluent configuration, you can do:

       1: var cfg = new Configuration()
       2:     .SetProperty(NHibernate.Cfg.Environment.ConnectionProvider, typeof(ResilientDriverConnectionProvider).AssemblyQualifiedName);

    From looking at the class, you can see that it supports two properties:

    • MaxTries: the maximum number of connect attempts;
    • DelayBetweenTries: the amount of time to wait between two connection attempts.

    It is possible to supply this values by configuration:

       1: var cfg = new Configuration()
       2:     .SetProperty(NHibernate.Cfg.Environment.ConnectionProvider, typeof(ResilientDriverConnectionProvider).AssemblyQualifiedName)
       3:     .SetProperties(ResilientDriverConnectionProvider.ConnectionMaxTries, "3")
       4:     .SetProperties(ResilientDriverConnectionProvider.ConnectionDelayBetweenTries, TimeSpan.FromSeconds(5).ToString());

    As usual, hope you find this useful! Smile

    Read more...