1

What I'm trying to achieve must be simple but I just can't get it to work. I have a simple table that contains an id and a description field.

Something like so:

 Medium
 ----------- 
 Id     Description
 ----------
 1      Watercolour
 2      Oil
 3      Etching
 4      Other

Because a user will have the opportunity to pick any of the items from a grid. I need to issue a Linq to NHibernate query to fetch the items the user picked.

I have the following test:

[Test]
public void LinqToNHibernate_Queries_Test()
{

    InSession(session =>
    {
        _mediumRepository = new NHibernateRepository<Medium>(session);

        Action<string> insertMedium = (description) =>
        {
            var medium = new Medium
            {
                Id = 0,
                MediumDescription = description
            };

            _mediumRepository.SaveOrUpdate(medium);
        };

        insertMedium("Watercolours");
        insertMedium("Oils");
        insertMedium("Etchings");
        insertMedium("Other");

        var itemIds = new[] {  "2" , "4"  }.Aggregate((x, y) => x + "," + y); 
        //var itemIds = new ItemId[] {new ItemId {Id = 2}, new ItemId {Id = 4}};
        //var items = _mediumRepository.GetAll().Where(med => itemIds.Any(i => i == med.Id));
        var items = _mediumRepository.GetAll().Where(med => itemIds.Contains(med.Id.ToString()));

        //var mediums = _mediumRepository.GetAll();

        //var items = mediums.Join(itemIds, m => m.Id, i => i.Id, (m, i) => m); 

        Assert.AreEqual(2, items.Count());
    });

I've tried a number of different methods including the Any operator but to no avail. The error I get with this particular attempt is a System.NotSupportedException : System.String ToString()

I guess all I'm trying to do is fetch a number of records where the Id exists in a subquery. In this example I want all the records from the mediums table where the id is 2 or 4.

I'm using Linq To NHibernate v3.0 against a SQLite database for my tests and SQL 2005 in production. Incidently using the same query with Linq To SQL and SQL 2005 works.

As I said this type of query must be common place and I'm sure I'm going to have a "DOH!!!" moment when one of you clever folks provides the answer.

2 Answers 2

1

Method calls and iterative constructs are generally hit-or-miss in most Linq to ORM implementations including Linq2NH. This is because in most cases the framework doesn't actually run the lambdas; it instead examines the IL of each expression node's lambda, and reverse-engineers the condition into a SQL expression (in Linq2NH it actually converts into NH criteria) by matching based on known patterns. If the lambda includes a method, even if the server-side code has access to that method, the framework often barfs because it can't translate a method call into SQL.

I would not use Linq for this particular query; try the ICriteria setup, and add an Expression.InG(med.Id.ToString(), itemIds) to the criteria.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks Keith, I was aware that linq implementations reverse engineer expression trees and the like but I'm surprised linq to NHibernate couldn't handle this simple (as i see it) query. As I mentioned L2SQL handles it. I was hoping to avoid NHibernate's other querying strategies if I could help it. I may just have to bite the bullet and give you're suggestion a try. Thanks for your help.
The NH Linq provider in NH 3 translates queries into HQL, not Criteria (which is what the NH 2.1.2 Linq provider did).
Good to know. My team's still using 2.x in our project.
0

The Linq2NH implimentation was indeed barfing on the ToString method as KeithS suggested. If I change my query to

var itemIds = new[] { 2, 4 }; 
var items = _mediumRepository.GetAll().Where(med => itemIds.Contains(med.Id));
Assert.AreEqual(2, items.Count());

Then my test passes.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.