3

Hi I am trying to return a collection of building domain.

private long _id;
private string _buildingName;
private IList<BasicRoom> _rooms;

I am using NHibernate and this mapping for the rooms

<bag name="rooms" table="tb_rooms" lazy="false">
<key column="buildingID"/>
<one-to-many class="Room"/>
</bag>

And I am calling the db like this;

Buildings = (List<Building>)session.CreateCriteria(typeof(Building)).AddOrder(Order.Asc("buildingName")).List<Building>();

The problem is I don't want the _rooms collection to be an IList but I need it to be a List. Alas, NHibernate requires that I use an Interface for collections. Any idea how to do this. I am new to .Net and thinking that maybe dropping NHibernate might be the way forward. I just need to get the collection typed as an List so I can move on. Any help much appreciated.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
user17510
  • 1,549
  • 5
  • 20
  • 37

3 Answers3

12

That's not how NHibernate works. You don't get to tell it what the concrete types of your domain model objects are. You only get to tell it what the base types and interfaces are. Then it gets to choose how to implement the domain types efficiently.

For example, NHibernate uses its own internal implementation of IList<T> that knows how to do lazy loading.

Moreover, NHibernate uses its own internal implementation of Building from your domain model. It is not necessarily the case that all the Building objects you will be using with NHibernate will have, as their concrete type, Building. It is only true that they will be Buildings, whether Building is the concrete type of your object, or whether it is the base type of the concrete type of your object.

But this is the right thing to do, since you are supposed to be using interfaces and base types instead of concrete types anyway. NHibernate helps you use all the right approaches to programming.

Now, why do you need a List<Building> per se? Why will IList<Building> not suffice?

yfeldblum
  • 65,165
  • 12
  • 129
  • 169
  • Thanks for this. The reason I need to map to List was that the AMF gateway I am using cannot map back to IList when objects come back from a flex ui to .net. I've solved by usings dtos which use List instead of Ilist and then I convert then as I need. Appreciated. – user17510 Feb 03 '09 at 07:00
  • 2
    There are fine reasons to use List over IList. List contains much more functionality for building useful predicates as one example. Having a tool force you to use interfaces is not "the right thing to do" to my opinion. it would be best if the POCOs were left alone and not wagged by the tail of your data provider. I would personally love it if list and bag mappings had better support for the List object. – MarkDav.is Oct 11 '10 at 16:44
5

Why do you need a concrete List object, when you can do everything you want with an IList?

If it absolutely has to be a concrete list, you have two options.

First, simply cast the IList<Building> to List<Building>. This will only work if the underlying type is a List<Building>, which I personally doubt.

Second, call the ToList() extension method on it:

Buildings = (List<Building>)session.CreateCriteria(typeof(Building)).AddOrder(Order.Asc("buildingName")).List<Building>().ToList();

I personally recommend that you do neither and use the IList instead.

Randolpho
  • 55,384
  • 17
  • 145
  • 179
  • I agree, you are better off dealing with the interface. It is much more flexible this way! – Jim Petkus Jan 30 '09 at 04:20
  • Thanks for the help. The reason is that when I send the object back (from the ui (flex)) after an update etc, the gateway will map the object back and then baulk at rooms being an IList. The gateway is forcing me to use List. – user17510 Jan 30 '09 at 04:59
  • Just to get the data out to flex and back in to the db via NHibernate is quite tricky. – user17510 Jan 30 '09 at 05:00
  • Well, if you have to you have to. Probably use ToList() rather than the cast, just in case the underlying type isn't List. – Randolpho Jan 30 '09 at 15:18
  • 4
    The best solution would be to change the gateway to take an IList (or better ICollection or IEnumerable) instead of concrete type. Keep use of concrete types to the narrowest scope possible. – Tim Scott Feb 01 '09 at 21:18
2

How about using the constructor of List<T> that takes an IEnumerable<T>? Then you can use:

Buildings = new List<Building>(session.CreateCriteria(typeof(Building)).AddOrder(Order.Asc("buildingName")).List<Building>());
Sean Carpenter
  • 7,681
  • 3
  • 37
  • 38