I have a class, Task, and it has a property TaskLibrary which is dll it will load and run some code from. So, any task has one library, but any library can have many tasks. My problem is that my test for making sure the task's Library property is not null is failing (so it could just be my test). My classes are effectively this:
public class Task
{
public virtual int TaskId {get;set;}
public virtual string Locked {get;set;}
public virtual int Status {get;set;}
public virtual TaskLibrary Library {get;set;}
}
public class TaskLibrary
{
public virtual int LibraryId {get;set}
public virtual string Name {get;set;}
public virtual string Description {get;set;}
public virtual byte[] Dll {get;set}
public virtual IEnumerable<Task> Tasks {get;set;}
}
My NHibernate mappings look like this:
<class name="Task">
<id name="Id" column="TaskId" type="Int32" unsaved-value="-1">
<generator class="identity"/>
</id>
<property name="Locked" column="Locked"/>
<property name="Status" column="Status"/>
<many-to-one name="Library" class="TaskLibrary" fetch="join"/>
</class>
<class name="TaskLibrary">
<id name="Id" column="LibraryId">
<generator class="identity"/>
</id>
<property name="Name"/>
<property name="Description"/>
<property name="Dll"/>
<set name="Tasks" lazy="true">
<key column="LibraryId"/>
<one-to-many class="Task"/>
</set>
</class>
My test class looks like this:
[TestFixture]
public class TaskRepositoryFixture
{
private ISessionFactory _sessionFactory;
private Configuration _configuration;
private readonly Task[] _tasks = new[]
{
new Task {Id = 1, Status = 1, Locked = 0, Library = new TaskLibrary { Id =1, Description = "Test Library", Name = "Tast.dll", Type = "RunnableTask", Dll = Encoding.ASCII.GetBytes("test binary data")}},
new Task {Id = 2, Status = 1, Locked = 0, Library = new TaskLibrary { Id =1, Description = "Test Library", Name = "Tast.dll", Type = "RunnableTask", Dll = Encoding.ASCII.GetBytes("test binary data")}},
new Task {Id = 3, Status = 1, Locked = 0, Library = new TaskLibrary { Id =2, Description = "Test Library 2", Name = "Tast2.dll", Type = "RunnableTask", Dll = Encoding.ASCII.GetBytes("test binary data")}},
new Task {Id = 4, Status = 1, Locked = 0, Library = new TaskLibrary { Id =2, Description = "Test Library 2", Name = "Tast2.dll", Type = "RunnableTask", Dll = Encoding.ASCII.GetBytes("test binary data")}},
new Task {Id = 5, Status = 1, Locked = 0, Library = new TaskLibrary { Id =3, Description = "Test Library 3", Name = "Tast3.dll", Type = "RunnableTask", Dll = Encoding.ASCII.GetBytes("test binary data")}},
};
private readonly TaskLibrary[] _libraries = new[]
{
new TaskLibrary { Id =1, Description = "Test Library", Name = "Tast.dll", Type = "RunnableTask", BinaryDll = Encoding.ASCII.GetBytes("test binary data")},
new TaskLibrary { Id =2, Description = "Test Library 2", Name = "Tast2.dll", Type = "RunnableTask", BinaryDll = Encoding.ASCII.GetBytes("test binary data")},
new TaskLibrary { Id =3, Description = "Test Library 3", Name = "Tast3.dll", Type = "RunnableTask", BinaryDll = Encoding.ASCII.GetBytes("test binary data")}
};
private void CreateInitialData()
{
using (ISession session = _sessionFactory.OpenSession())
using (ITransaction transaction = session.BeginTransaction())
{
foreach (var lib in _libraries)
session.Save(lib);
foreach (var task in _tasks)
session.Save(task);
transaction.Commit();
}
}
[TestFixtureSetUp]
public void TestFixtureSetUp()
{
_configuration = new Configuration();
_configuration.Configure();
_configuration.AddAssembly("DistPollAutoTasksShared");
_sessionFactory = _configuration.BuildSessionFactory();
}
[SetUp]
public void SetupContext()
{
new SchemaExport(_configuration).Execute(false, true, false, false);
CreateInitialData();
}
[Test]
public void CanGetLibraryFromTask()
{
ITaskRepository repository = new TaskRepository();
var fromDb = repository.GetById(_tasks[0].Id);
Assert.IsNotNull(fromDb.Library);
Assert.IsNotNull(fromDb.Library.Dll);
}
}
And, the Tasks table in the MSSQL2000 database is this:
CREATE TABLE [dbo].[Tasks](
[TaskId] [int] IDENTITY(1,1) NOT NULL,
[TaskLibrary] [int] NOT NULL,
[Status] [int] NOT NULL,
[Locked] [int] NOT NULL
)
If you're still with me...
From my Task class, I just want an instance of the TaskLibrary class for the Library property. Also, if I'm working with the libraries themselves, I want to be able to lazily retrieve an IEnumerable of all tasks using that library. However, when I run the test, I get this error:
TestCase 'DistPollAutoTasksShared.Tests.TaskRepositoryFixture.CanGetLibraryFromTask'
failed: NHibernate.LazyInitializationException : Could not initialize proxy - no Session.
at NHibernate.Proxy.AbstractLazyInitializer.Initialize()
at NHibernate.Proxy.AbstractLazyInitializer.GetImplementation()
at NHibernate.Proxy.Poco.Castle.CastleLazyInitializer.Intercept(IInvocation invocation)
at Castle.DynamicProxy.AbstractInvocation.Proceed()
at TaskLibraryProxy2bd44073e90f47298039abfbfda11492.get_Dll()
This is the first time I've used NHibernate, so I'm still learning. I really want to get a good foundation of the basics, so I'm stuck here until then. Any help, suggestions, reading material (I've read all of this question's suggestions and some others) would be appreciated.
EDIT:
After changing fetch="join", I'm getting the functionality I want from the Task class. However, I've added another test for the Tasks property of the TaskLibrary class:
[Test]
public void CanGetTasksByLibrary()
{
ITaskLibraryRepository repository = new TaskLibraryRepository();
var fromDb = repository.GetById(_libraries[0].Id).Tasks;
Assert.IsNotNull(fromDb);
Assert.True(fromDb.Count() == 2, "Cannot get IEnumerable<Task> from TaskLibrary");
}
But, an assertion fails with this error (I've updated the code above to reflect any changes I've made):
TestCase 'DistPollAutoTasksShared.Tests.TaskLibraryRepositoryFixture.CanGetTasksByLibrary'
failed:
Cannot get IEnumerable<Tasks> from TaskLibrary
Expected: True
But was: False