views:

226

answers:

2

I have a basic NHibernate.Linq query:

var items = from item in session.Linq<ObjectType>()
             where item.ID > 0
             select new { ID = item.ID, Type = item.ClassName };

This works fine. However, ObjectType is a heavy-weight class, and I only want ID and ClassName. So I've created a DTO called EntityInfo:

public class EntityInfo
{
    public String ID { get; set; }
    public String Type { get; set; }
}

And I want to return an IEnumerable<EntityInfo>:

return from item in session.Linq<ObjectType>()
       select new EntityInfo() { ID = item.ID.ToString(), Type = item.ClassName };

Upon attempting to iterate through the returned IEnumerable, though, I get the following exception:

System.ArgumentOutOfRangeException : Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index
    at System.ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource)
    at System.ThrowHelper.ThrowArgumentOutOfRangeException()
    at System.SZArrayHelper.get_Item[T](Int32 index)
    at System.Collections.ObjectModel.ReadOnlyCollection`1.get_Item(Int32 index)
    at NHibernate.Linq.Visitors.SelectArgumentsVisitor.VisitMethodCall(MethodCallExpression expr)
    at NHibernate.Linq.Visitors.ExpressionVisitor.Visit(Expression exp)
    at NHibernate.Linq.Visitors.NHibernateExpressionVisitor.Visit(Expression exp)
    at NHibernate.Linq.Visitors.ExpressionVisitor.VisitList(ReadOnlyCollection`1 original)
    at NHibernate.Linq.Visitors.ExpressionVisitor.VisitNew(NewExpression nex)
    at NHibernate.Linq.Visitors.SelectArgumentsVisitor.VisitNew(NewExpression expr)
    at NHibernate.Linq.Visitors.ExpressionVisitor.Visit(Expression exp)
    at NHibernate.Linq.Visitors.NHibernateExpressionVisitor.Visit(Expression exp)
    at NHibernate.Linq.Visitors.RootVisitor.HandleSelectCall(MethodCallExpression call)
    at NHibernate.Linq.Visitors.RootVisitor.VisitMethodCall(MethodCallExpression expr)
    at NHibernate.Linq.Visitors.ExpressionVisitor.Visit(Expression exp)
    at NHibernate.Linq.Visitors.NHibernateExpressionVisitor.Visit(Expression exp)
    at NHibernate.Linq.Visitors.NHibernateQueryTranslator.Translate(Expression expression, QueryOptions queryOptions)
    at NHibernate.Linq.NHibernateQueryProvider.TranslateExpression(Expression expression)
    at NHibernate.Linq.NHibernateQueryProvider.Execute(Expression expression)
    at NHibernate.Linq.Query`1.GetEnumerator()

Is ToString() not allowed inside the select statement? I've gotten around it by running the original query, then creating a new enumerable by manually mapping the anonymous type to EntityInfo instances, but I'd obviously prefer the previous version.

For reference, I'm using NHibernate.Linq 1.0.0.4000, NHibernate 2.1.0.4000, and FluentNHibernate 1.0.0.593.

+1  A: 

Did you mean to use object initializer, instead of an array initializer?

return from item in session.Linq<ObjectType>()
   select new EntityInfo() { ID = item.ID.ToString(), Type = item.ClassName };
RKitson
You're absolutely right. I'll edit the question accordingly.
Dathan
A: 

I have same problem with .ToString(), It seems it is not allowed in LINQ-to-NHibernate query. My work-around was not just comparing numerical values. For your problem I suggest using following class and query:

public class EntityInfo
{
private String _id;    
public int ID { 
get {return _id.ToString();}
set {_id = Convert.ToInt32(value);}; 
}
    public String Type { get; set; }
}

return from item in session.Linq<ObjectType>()
       select new EntityInfo() { item.ID, item.ClassName };
afsharm
I ended up taking pretty much this approach. However, since it's just a DTO, the public properties are all that matter, and I want to keep the public type of ID as String. So I just went ahead and gave EntityInfo a public constructor that accepts an int for ID and performs the appropriate conversion.
Dathan