Using ASP.NET/C#/fluent Hibernate architecture, I am trying to use a GridView
and ObjectDataSource
to manage my business objects. I have a main class Project
with a one-to-many relationship with OIC
- simplified mappings and classes below.
// OIC class definition
public partial class OIC
{
public int pkOICID { get; set; }
public string Guarantor { get; set; }
// ... other fields
public Project Project { get; set; }
}
// OIC mapping
public class OICMap : ClassMap<OIC>
{
public OICMap()
{
Table(@"OIC");
LazyLoad();
Id(x => x.pkOICID) // primary key for OIC
.Column("pkOICID")
.Not.Nullable()
.GeneratedBy.Identity();
Map(x => x.Guarantor)
.Column("Guarantor")
.Not.Nullable();
// ...more fields not listed
References(x => x.Project) // foreign key to Project
.Class<Project>()
.Access.Property()
.Cascade.None()
.LazyLoad()
.Columns("fkProjectID");
}
}
// Project class definition
public partial class Project
{
public int pkProjectID { get; set; }
// ...
public Iesi.Collections.ISet OICs { get; set; }
}
// Project mapping
public class ProjectMap : ClassMap<Project>
{
public ProjectMap()
{
Table(@"Project");
LazyLoad();
Id(x => x.pkProjectID)
.Column("pkProjectID")
.Not.Nullable()
.GeneratedBy.Identity();
// ...
HasMany<OIC>(x => x.OICs)
.Access.Property()
.AsSet()
.Cascade.AllDeleteOrphan()
.LazyLoad()
.Inverse()
.Not.Generic()
.KeyColumns.Add("fkProjectID", mapping => mapping.Name("fkProjectID")
.SqlType("int")
.Not.Nullable());
}
}
When doing unit testing on my repositories, all of the CRUD operations for the OIC class worked perfectly, so I know that the mappings work. However, when I use a GridView
and ObjectDataSource
to try and delete an instance of OIC, I get a "not-null property references a null or transient value CLS.BusinessLayer.Model.OIC.Guarantor" exception when I try to commit the transaction.
Setting a breakpoint and inspecting the object in the repository's Remove function (code below) reveals that only the primary key for the OIC object is being populated - the rest of the fields are null.
public virtual void Remove(T entity)
{
if (entity == null)
throw new ArgumentNullException("entity");
_session = NHibernateSessionProvider.GetSession();
if (!_session.Transaction.IsActive)
{
try
{
using (ITransaction transaction = _session.BeginTransaction())
{
_session.Delete(entity);
transaction.Commit(); // exception caused here
}
}
catch
{
}
}
else
_session.Delete(entity);
}
If I remove the .Not.Nullable()
on the Guarantor property in OIC, the delete works fine (I only tried this out of curiosity). Also, if I include the Guarantor field in the list of DataKeyNames
for my GridView
, the field is correctly populated when I inspect the object in the Remove()
function above, and the transaction commits successfully. Currently, the GridView
only contains pkOICID - the primary key, in DataKeyNames
.
So there are a couple things I am stuck on:
GridView
or ObjectDataSource
that is causing the object not to be fully populated before being deleted - is this something that needs to be done in ObjectDataSource_Deleting()
or elsewhere?Please let me know if more code or explanation is needed - thank you.
this should work to delete when only the id is known/populated
session.Delete(Session.Get(entity.GetType(), entity.Id);