Given a Vehicle class and a VehicleProperty class...
public class Vehicle
{
public virtual int Id { get; protected set; }
public virtual string Registration { get; set; }
private List<VehicleProperty> _properties = new List<VehicleProperty>();
public virtual IEnumerable<VehicleProperty> Properties
{
get { return _properties; }
protected set{ _properties = new List<VehicleProperty>(value);}
}
public virtual void AddProperty(string name, string value)
{
_properties.Add(new VehicleProperty {Name = name, Value = value});
}
}
public class VehicleProperty
{
public virtual string Name { get; set; }
public virtual string Value { get; set; }
}
How can I map the two classes so that the VehicleProperty table has a composite key of [VehicleId] and [Name]. Vehicle would be an aggregate root (VehicleProperty is not accessed outside of a Vehicle class).
I have tried everything that I can think of (I'm new to NHibernate so that's not much)
public class VehicleMap : ClassMap<Vehicle>
{
public VehicleMap()
{
Id(x => x.Id);
Map(x => x.Registration);
HasMany(x => x.Properties)
.Inverse()
.Cascade.All();
}
}
public class VehiclePropertyMap : ClassMap<VehicleProperty>
{
public VehiclePropertyMap()
{
UseCompositeId()
.WithKeyProperty(x => x.Name)
.WithKeyReference(x => x.Vehicle, "Vehicle_Id");
Map(x => x.Name);
Map(x => x.Value);
}
}
This mapping results in the below sql and a StaleStateException "Unexpected row count: 0; expected: 1" (I also don't really want to have a Vehicle property on the VehicleProperty)...
INSERT INTO "Vehicle" (Registration) VALUES (@p0); select last_insert_rowid(); @p0 = 'AA09CDE'
UPDATE "VehicleProperty" SET Name = @p0, Value = @p1 WHERE Name = @p2 AND Vehicle_Id = @p3; @p0 = 'Colour', @p1 = 'Black', @p2 = 'Colour', @p3 = ''
First, create a separate class for the composite PK:
Then, refactor the
VehicleProperty
class this way:Finally, the maps:
(NHibernate 3.3.1 and FluentNHibernate 1.3.0)
I agree entirely with Stefan's points, and although I can't attest to the correctness of his mapping, the literal translation into Fluent NHibernate is as follows:
I don't know FluentNHibernate to show you the code. I can tell you how it looks in XML.