Hi all. I am a Java developer turned .NET developer, and I've got some small projects that use LINQ to SQL that I'm considering switching over to user NHibernate. (LINQ to SQL frustrates me. I spend lots of time trying to figure out what how to write my business logic in such a way that it doesn't depend on LINQ to SQL's oddities.) Anyway, I put together a simple example to try most of the things I do with LINQ to SQL to see if I can use NHibernate, and I'm impressed, but I ran into an issue.
In my example, I have a one-to-many from one cat many toys (I was using the QuickStart as a starting point), and I get the following error when I try to execute the following code:
Code:
IList<Cat> dbCats = session.Query<Cat>().Where(cat => cat.Toys.Any(t => t.Shape == "Bird")).ToList();
I get the following error:
Code:
Could not load type cat.Toys. Possible cause: the assembly was not loaded or not specified.
Any ideas? I've included my example program as well as the two mapping files. If I comment out the define directive, it runs to completion, and I get what one would expect. If I ignore the exception, the program just sits there.
Thank you for the excellent tool.
Don
Main program:
Code:
#define FAIL
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate;
using QuickStart;
using NHibernate.Linq;
namespace QuickStart
{
class Program
{
static void Main(string[] args)
{
try
{
ISession session = NHibernateHelper.GetCurrentSession();
ITransaction tx = session.BeginTransaction();
Cat mitzi = new Cat
{
Name = "Mitzi"
, Sex = 'F'
, Weight = 4.2f
};
Cat todd = new Cat
{
Name = "Todd"
, Sex = 'M'
, Weight = 8f
};
session.Save(mitzi);
session.Save(todd);
Toy mouse = new Toy
{
OwnerCatId = mitzi.Id.Value
, Shape = "Mouse"
};
Toy bird = new Toy
{
OwnerCatId = todd.Id.Value
, Shape = "Bird"
};
session.Save(mouse);
session.Save(bird);
tx.Commit();
#if FAIL
IList<Cat> dbCats = session.Query<Cat>().Where(cat => cat.Toys.Any(t => t.Shape == "Bird")).ToList();
#else
IList<Cat> dbCats = session.Query<Cat>().Where(cat => new String[] { "Mitzi", "Todd" }.Contains(cat.Name)).ToList();
#endif
foreach (Cat dbCat in dbCats)
{
Console.Out.WriteLine(
"{0}: {1}"
, dbCat.Id
, dbCat.Name
);
}
List<Toy> dbToys = session.Query<Toy>().ToList();
foreach (Toy dbToy in dbToys)
{
Console.Out.WriteLine(
"{0}: {1}"
, dbToy.ToyId
, dbToy.Shape
);
}
NHibernateHelper.CloseSession();
}
catch(Exception ex)
{
Console.WriteLine(ex);
}
Console.ReadKey();
}
}
}
Cat.cs, Cat.hbm.xml:
Code:
using Iesi.Collections.Generic;
using System;
namespace QuickStart
{
public class Cat
{
//private string id;
private Int32? id;
private string name;
private char sex;
private float weight;
private ISet<Toy> toys;
public Cat()
{
}
//public virtual string Id
//{
// get { return id; }
// set { id = value; }
//}
public virtual Int32? Id
{
get { return id; }
set { id = value; }
}
public virtual string Name
{
get { return name; }
set { name = value; }
}
public virtual char Sex
{
get { return sex; }
set { sex = value; }
}
public virtual float Weight
{
get { return weight; }
set { weight = value; }
}
public virtual ISet<Toy> Toys
{
get { return toys; }
set { toys = value; }
}
}
}
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
namespace="QuickStart" assembly="QuickStart">
<class name="Cat" table="Cat">
<!-- A 32 hex character is our surrogate key. It's automatically
generated by NHibernate with the UUID pattern. -->
<!--<id name="Id">
<column name="CatId" sql-type="char(32)" not-null="true"/>
<generator class="uuid.hex" />
</id>-->
<id name="Id">
<column name="CatId" sql-type="INT" not-null="true" />
<generator class="identity" />
</id>
<!-- A cat has to have a name, but it shouldn't be too long. -->
<property name="Name">
<column name="Name" length="16" not-null="true" />
</property>
<property name="Sex" />
<property name="Weight" />
<set name="Toys" inverse="true" table="TOY">
<key>
<column name="OWNER_CAT_ID" not-null="true" />
</key>
<one-to-many class="Toy" />
</set>
</class>
</hibernate-mapping>
Toy.cs, Toy.hbm.xml:
Code:
using Iesi.Collections.Generic;
using System;
namespace QuickStart
{
public class Toy
{
private Int32? toyId;
//private String ownerCatId;
private Int32 ownerCatId;
private String shape;
private Cat ownerCat;
public virtual Int32? ToyId
{
get { return toyId; }
set { toyId = value; }
}
//public virtual String OwnerCatId
//{
// get { return ownerCatId; }
// set { ownerCatId = value; }
//}
public virtual Int32 OwnerCatId
{
get { return ownerCatId; }
set { ownerCatId = value; }
}
public virtual String Shape
{
get { return shape; }
set { shape = value; }
}
public virtual Cat OwnerCat
{
get { return ownerCat; }
set { value = ownerCat; }
}
}
}
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
namespace="QuickStart" assembly="QuickStart">
<class name="Toy" table="TOY">
<id name="ToyId">
<column name="TOY_ID" sql-type="INT" not-null="true" />
<generator class="identity" />
</id>
<property name="OwnerCatId">
<column name="OWNER_CAT_ID" sql-type="CHAR(32)" length="32" not-null="true" />
</property>
<property name="Shape">
<column name="SHAPE" sql-type="NVARCHAR(16) NULL" length="16" not-null="false" />
</property>
</class>
</hibernate-mapping>