views:

77

answers:

3

As an example, let's say you have a class like such

**Person**
int PersonID
string PersonName
BusinessLocation Locations

**BusinessLocation**
string city
string state
List<int> ZipCodes

(saying that the locations may exist in multiple zipcodes)
(also ignoring that zipcodes should be strings instead of ints, this is just an example)

Say that the locations of the Businesses exist in multiple zipcodes.

Now I am trying to pull back all the people in the person table, given a business zipcode.

For example, I want all the people who have a zipcode of 32567.

(Given a list of IDs, this works, I am trying to do the opposite, given one ID, I want a list of people)

public Person GetPersonsByBusinessZipCode(int zipcode)
{
    List<Person> personList = this.GetAllQueryable().Where(x => x.Locations.ZipCodes.Contains(zipcode)).ToList();
}

This is Mapped Like such in Fluent.

HasMany<int>(x => x.ZipCodes)
   .Table("BusinessLocationsZipCodes")
   .KeyColumns.Add("BusinessLocationID")
   .Inverse()
   .Element("ZipCode")
   .AsBag()
   .Cascade.None()
   .Cache.ReadOnly();

BusinessLocationZipCodes is just a reference table alluding that a BusinessLocation can have multiple ZipCodes, hence the HasMany.

Knowing that the reverse works, if I am given a list of ZipCodes and I am trying to find BusinessLocations contained in the list of zipcodes works (as long as the mapping is to a zipcode and not a List of zipcodes). Now I'm just trying to find the BusinessLocations given a zipcode.

If anyone has an answer, I would appreciate it.

A: 

Linq provider shouldn't matter much as long as you're using System.Linq.Queryable and the IQueryable interface.

I believe you are looking for the Queryable.Any method.

Persons.Where(p => p.Locations.ZipCodes.Any(z => z == zipCode))

Or, if your Persons have many Locations:

IQueryable<Person> query =
  from p in Persons
  where
  (
    from l in p.Locations
    from z in l.ZipCodes
    select z
  ).Any(z => z == zipCode)
  select p;
David B
Thanks David, but with this I received an error that stated "Could not understand y = 32567"
Matt Braunwart
1. The linq provider matters because they both have different incompletions. The one from NHiberante.Linq.dll is deprecated now.2. With a fully implemented linq provider, it should not matter if you use Any(x => x == y) or Contains(y) technically. Contains is preferred because it is more readable.
Paco
@Matt Braunwart - I have not used y in my code, so it is difficult for me to troubleshoot your problem. Could it be that y has a property that is more properly compare-able with a zipcode? Also - perhaps == (comparison) would be more appropriate than = (assignment)
David B
@Paco I must disagree. The lack of a Contains<T>(this IQueryable<T> source, T item) method on System.Linq.Queryable leads me to believe that the Linq Authors intended for Any<T>(this IQueryable<T> source, Expression<Func<T, bool>> filter) to be canon. If you want to support your position, please point out some evidence in the framework that Contains is to be preferred in LinqToAnything.
David B
There is no lack of contains in the Linq implementation in the trunk. Contains works works for most queries. You can find the contains extension method you mention on msdn. Methods implemented by a linq provider in the expression of a where clause do not necessarily need to be extensions of IQueryable. The Zipcodes property probably isn't IQueryable. If you think Any(x => x == y) is more readable than Contains(y), it is better to use Any for you of course. I don't know how to give evidence that I actually prefer one way over the other. I try to explain that your answer is about readability.
Paco
I stand corrected. Of course Queryable has a Contains method. How silly.
David B
A: 

What's the exception? That should work correctly using the latest NHibernate build (2.1.2.400).

// The following query: (never mind the Spanish)

var transporte = // some entity;
var solicitud  = IQueryable<Solicitud>
                   .Where(x => x.SolicitudesDeTransporte.Contains(transporte)).ToList();

Generates:

SELECT this_.Id as Id6_0_,
       /* etc... */
FROM   Solicitud this_
WHERE  this_.Id in (SELECT this_0_.Id as y0_
                    FROM   Solicitud this_0_
                           left outer join Solicitud_Transporte solicitude1_
                             on this_0_.Id = solicitude1_.Id_Solicitud
                    WHERE  solicitude1_.Id = 1 /* :p0 */)
Rafael Belliard
The exception i get is a Object Null Reference. But I can get the list of ZipCodes, its just it wont let me query further into the list using the contains. (that is when it throws the exception)
Matt Braunwart
A difference between your query and the posted query is that you use an entity (with id) in the contains and in the question a value object (without id) is used.
Paco
@Matt Braunwart: what is null that shouldn't be null?
Paco
A: 

Paco, apparently I screwed up because I had two accounts floating out here that I did not know about, so this is my OpenID one. Anyhow I am not sure of the NullReferenceException, it dives down into NHibernate namespaces with no link back to any of the classes I am working with. But I only get the NullReferenceException when I try to dive into it using Contains. As I state above, I do not get the NullReferenceException if I am just bring back the list of ZipCodes. So my mapping works, but it can not seem to return me a List of BusinessLocations based on the Contains statement.

Matt Braunwart
I'm sorry, not correctly stated, the only link back is to the class I'm working with, the repository, which invokes the call.
Matt Braunwart