Category Archives: NHibernate

FreeTextExpression for NHibernate 3.2

I upgraded to the latest NHibernate 3.2 and found my FreeText AbstractCriterion wasn’t working as it previously did. ┬áThis updated version works for me:

[Serializable]
public class FreeTextExpression : AbstractCriterion
{
  private readonly string _propertyName;
  private readonly object _value;
  private readonly IProjection _projection;

  /// <summary>
  /// Initializes a new instance of the <see cref="FreeTextExpression"/> class.
  /// </summary>
  /// <param name="projection">The projection.</param>
  /// <param name="value">The value.</param>
  public FreeTextExpression(IProjection projection, object value)
  {
    _projection = projection;
    _value = value;
  }

  /// <summary>
  /// Initialize a new instance of the <see cref="FreeTextExpression" />
  /// class for a named Property and its value.
  /// </summary>
  /// <param name="propertyName">The name of the Property in the class.</param>
  /// <param name="value">The value for the Property.</param>
  public FreeTextExpression(string propertyName, object value)
  {
    _propertyName = propertyName;
    _value = value;
  }

  public override SqlString ToSqlString(ICriteria criteria, ICriteriaQuery criteriaQuery, IDictionary<string, IFilter> enabledFilters)
  {
    var sqlBuilder = new SqlStringBuilder();
    var columnNames = CriterionUtil.GetColumnNames(_propertyName, _projection, criteriaQuery, criteria, enabledFilters);

    if (columnNames.Length != 1)
    {
      throw new HibernateException("Contains may only be used with single-column properties");
    }

    sqlBuilder.Add("freetext(")
      .Add(columnNames[0])
      .Add(",");

    sqlBuilder.Add(criteriaQuery.NewQueryParameter(GetParameterTypedValue(criteria, criteriaQuery)).Single());
    sqlBuilder.Add(")");

    return sqlBuilder.ToSqlString();
  }

  public override TypedValue[] GetTypedValues(ICriteria criteria, ICriteriaQuery criteriaQuery)
  {
    var typedValues = new List<TypedValue>();

    if (_projection != null)
    {
      typedValues.AddRange(_projection.GetTypedValues(criteria, criteriaQuery));
    }
    typedValues.Add(GetParameterTypedValue(criteria, criteriaQuery)); 

    return typedValues.ToArray();
  }

  public TypedValue GetParameterTypedValue(ICriteria criteria, ICriteriaQuery criteriaQuery)
  {
    var matchValue = _value.ToString();
    if (_projection != null)
    {
      return CriterionUtil.GetTypedValues(criteriaQuery, criteria, _projection, null, matchValue).Single();
    }
    return new TypedValue(NHibernateUtil.String, _value.ToString(), EntityMode.Poco);
  }

  public override IProjection[] GetProjections()
  {
    if (_projection != null)
    {
      return new [] { _projection };
    }
    return null;
  }

  public override string ToString()
  {
    return " freetext(" + (_projection ?? (object)_propertyName) + "," + _value + ")";
  }
}

NHibernate QueryOver Support For OrderBy Random

I had a need to get random records from the database, so I came up with this extension to the NHibernate QueryOver api. It is for Microsoft SQL Server, but it shouldn’t take much effort to port it to other database flavors.

public static class NHibernateExtensions
{
  public static IQueryOver<TRoot, TSubType> OrderByRandom<TRoot, TSubType>(this IQueryOver<TRoot, TSubType> query)
  {
    query.UnderlyingCriteria.AddOrder(new RandomOrder());
    return query;
  }
}

public class RandomOrder : Order
{
  public RandomOrder() : base("", true)
  {
  }

  public override SqlString ToSqlString(ICriteria criteria, ICriteriaQuery criteriaQuery)
  {
    return new SqlString("newid()");
  }
}