tags:

views:

204

answers:

4

Hello, I'm trying to return all entities where a given property is not empty. The problem is IsNotEmpty() only applies to collections. Below is the general approach I've taken so far, it obviously doesn't work.

ICriteria lvCriteria = NHibernateHelper.GetCurrentSession()
                                       .CreateCriteria(typeof(FunctionCall))
                                       .SetMaxResults(100)
                                       .AddOrder(Order.Desc("LogId"));

if (pvMsg.HasValue)
{                
       lvCriteria.Add(Restrictions.IsNotNull("Msg"))
                 .Add(Restrictions.IsNotEmpty("Msg"));
}

Any suggestions? Is it possible to achieve this result by checking the property value's length? Thank you!

A: 

I believe you're looking for:

.Add(Expression.IsNotEmpty("PropertyName"));

and

.Add(Expression.IsNotNull("PropertyName"));
statichippo
In fact that is not what I'm looking for. IsNotEmpty() applies only to collections (i.e. bags, sets, etc.)! If I am wrong, please let me know. I would like to check the value of "Msg" for each individual entity and return only those who have a value. The equivalent of if(!string.IsNullOrEmpty(pvMsg)) { ... }
alan
Expression.IsNotEmpty() is the same as !string.IsNullOrEmpty().
statichippo
Notice that I'm using the EXPRESSION class, not the RESTRICTIONS class (as you did in the post)
statichippo
Yes I did notice the difference - I had before and have since tried Expression in place of Restrictions..these both result in the following MappingException:Property path [Assembly.Domain.FunctionCall.Msg] does not reference a collectionThank you.
alan
statichippo
A: 

Below are my mapping and class definition:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-import="true" assembly="Domain" namespace="Assembly.Domain">
  <class name="Assembly.Domain.FunctionCall, Domain" lazy="false" table="FunctionCallLog">

    <id name="LogId" column="LogId">
      <generator class="native" />
    </id>

    <property name="LogTime" column="LogTime" />
    <property name="Username" column="Username" />
    <property name="CallerIp" column="CallerIp" />
    <property name="FunctionName" column="FunctionName" />
    <property name="Parameters" column="Parameters" />
    <property name="Msg" column="Msg" />
    <property name="FileName" column="FileName" />
    <property name="TimeSpan" column="TimeSpan" />

  </class>
</hibernate-mapping>


using System;

namespace Assembly.Domain
{
    public class FunctionCall
    {
        public int LogId { get; set; }
        public DateTime LogTime { get; set; }
        public string Username { get; set; }
        public string CallerIp { get; set; }
        public string FunctionName { get; set; }
        public string Parameters { get; set; }
        public string Msg { get; set; }
        public string FileName { get; set; }
        public int TimeSpan { get; set; }
    }
}
alan
A: 

Try this:

ICriteria lvCriteria = NHibernateHelper.GetCurrentSession()
                                       .CreateCriteria(typeof(FunctionCall))
                                       .SetMaxResults(100)
                                       .AddOrder(Order.Desc("LogId"));

if (pvMsg.HasValue)
{                
       lvCriteria.Add(Restrictions.IsNotNull("Msg"))
                 .Add(Restrictions.Not(Restrictions.Eq("Msg", ""));
}

There may be a more compact way of expressing this.

Jamie Ide
I've tried that as well, it does not work as expected.I guess I should make clear that perhaps IsNotEmpty() does not work because I need to apply this filter as the collection is being populated; this is to avoid a timeout as this table contains 1,000,000+ records.
alan
What do you mean by "I need to apply this filter as the collection is being populated"? If the query is timing out then you should grab the SQL issued by NH execute it directly and inspect the query execution plan.
Jamie Ide
It times out due to the amount of data coming back; it uses ungodly amounts of server memory. Is it not possible to say 'only grab entities whose Msg property contains a value' rather than 'grab all Msgs then return only those whose Msg property have a value'?I.E. only picking the good apples off the tree rather than picking all the apples and then throwing out the bad ones?
alan
The Criteria API generates a SQL statement that is executed on the database server. There is no client side filtering done. I strongly suggest you profile your application to see the SQL statements are being issued.
Jamie Ide
A: 

Finally, I discovered the combination I was looking for!

lvCriteria.Add(Restrictions.Not(Expression.Eq("Msg", string.Empty)));

This combination of Restrictions and Expression works as expected; narrowing out all empty strings. I do not know why I could not achieve these results earlier even with:

lvCriteria.Add(Restrictions.Not(Restrictions.Eq("Msg", string.Empty)));

Thank you to all who tried.

alan