views:

325

answers:

2

In such a query:

var q = from l in session.Linq<Letter>()
    where
    letterTypeSearch == null ? true : 
        (l.LetterType.ToString() == letterTypeSearch)

l.LetterType is an Enum.

UPDATE It seems that's impossible to compare Enums in current linq-to-nhibernate. While letterTypeSearch is a string containing a LetterType instance that is ToString()ed and LetterType is inherited from int, there 3 ways of comparisons:

1- Comparing in String: It impossible because l.LetterType.ToString() produces "(ArgumentOutOfRangeException): Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: index, " error.

2- Comparing in Enum (LetterType) itself: It is impossible too because l.LetterType == LetterType.Internal results in "(QueryException): Type mismatch in NHibernate.Criterion.SimpleExpression: LetterType expected type System.Int32, actual type Faraconesh.EnterpriseAppUnits.OfficeAutomation.BusinessEntities.LetterType, " error.

3- Comparing in Int32: Yet not possible, because Convert.ToInt32(l.LetterType) generates "(NotImplementedException): The method ToInt32 is not implemented., " error.

So how can I compare Enums in LINQ-to-NHibernate? Is this problem specific to LINQ-to-NHibernate or all LINQ users have such a problem?

UPDATE2 here are class, enum and mapping (smmarized):

    public class Letter
    {
        private LetterType _letterType;
        public LetterType LetterType
        {
            set
            {
                _letterType = value;
            }//end  
            get
            {
                return _letterType;
            }//end  
        }
}

=========

public enum LetterType { Incoming = 0, Outgoing = 1, Internal = 2, }

=========

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-lazy="false">
  <class
       name="Faraconesh.EnterpriseAppUnits.OfficeAutomation.BusinessEntities.Letter,Faraconesh.EnterpriseAppUnits.OfficeAutomation.BusinessEntities"
        table="OfficeAutomation_Letter">

    <property
         name="LetterType" column="LetterType"
         type="int" update="true" insert="true" access="property"
         not-null="true"/>

  </class>
</hibernate-mapping>
A: 

If I were you, I create a Dot net Enum with these nhibernate Enum and then compare them with dot net equals.

Nasser Hadjloo
What do you mean by nhibernate enum? There is just one enum and that is dotnet Enum.
afsharm
@Afshar, As I underestandyour question, You want to compare an Enum with a Nhibernate Result. and I suggest you to store NHibernate result to a standard .net Enum and then compare these 2 enums together.
Nasser Hadjloo
+1  A: 

You have mapped the enum as type="int" which causes the error, probably because there are no implicit conversions to and from int. If you drop the type attribute, the enum will be mapped to an int value in the database and the Linq queries will work.

Note also that in your property mapping every attribute except name and type are unnecessary as they specify the default values. "Name" is the only required attribute on a property mapping, see section property in the reference documentation.

<property name="LetterType" />

Using the latest (2.1.2GA) version of NHibernate.Linq, which is available from the NHibernate Core download link on nhforge.org, the following queries with enums work as expected.

var q = from l in session.Linq<Letter>()
    where l. LetterType == LetterType.A4
    select l;
var result = q.ToList<Letter>();

LetterType? ltype = LetterType.A4;
q = from l in session.Linq<Letter>()
    select l;
if (code != null) {
    q = q.Where( l => l.LetterType == ltype.Value );
}
result = q.ToList<Letter>();

However, this form of the last query will not work if ltype is null as the query parser will still try to use ltype.Value.

q = from l in session.Linq<Letter>()
    where ltype != null && l => l.LetterType == ltype.Value
    select l;
result = q.ToList<Letter>();
Lachlan Roche
@Lachlan, I'm using same query, but mine is not working.
afsharm
@Lachlan, I'm afraid it may be because of way the Enum is mapped. Mine is using: <property name="LetterType" column="LetterType" type="int" update="true" insert="true" access="property" not-null="true" />May be this the cause of the problem?
afsharm
@afsharm Yes thats it.
Lachlan Roche
@afsharm Can you add your mapping with type=int to the question.
Lachlan Roche
@Lachlan, see UPDATE2
afsharm
@Lachlan: Many thanks for your solution, you really saved me from nightmares! But have one more question: I dropped `type="int"` and everything went O.K. But I thought `type` attribute was mandatory, wasn't it?
afsharm