Hello all, I have an error which seems to not matter how much I google and try to fix it.
I've read and tried to solve using the following topics (the closest I've found related to my issue): Fluent NHibernate and Collections Mapping // http://marekblotny.blogspot.ca/2009/02/fluent-nhbernate-and-collections.html How to cascade Save with CompositeId in NHibernate? https://groups.google.com/d/topic/nhusers/7M-MI8RLalg/discussion How to map an objectified Many to Many relationship? https://groups.google.com/d/topic/nhusers/OwyWQrsqTqc/discussion 4 tables are involved in my mapping: Member, Vehicle, MemberVehicles and LastUsedVehicles. Tables Member and Vehicle are business objects in the application Table MemberVehicles is a association table (Many to many) with no extra columns -> The mapping is OK Table LastUsedVehicles has a composite key using Vehicle and Member Ids and an extra column to store timestamp. This table doesn't not link member and Vehicles then. The mapping of this table is my issue. What I need is when deleting a Member, deleting all his vehicles (working fine using many to many table) and delete all data in LastUsedVehicles for all combinations of Member and his vehicles. Tables in DB Member Member_uid (PK) | Others Vehicle Vehicle_uid (PK) | Others MemberVehicles - Many to many -> map is working Member_uid (PK/FK) | Vehicle_uid (PK/FK) (No extra columns) LastUsedVehicles Vehicle_uid (PK/FK) | Member_uid (PF/FK) | DateLastUsed (Not Null) Mappings Member public class MemberMap : ClassMap<Member> { public MemberMap() { Table("wpmember.member"); // ... HasManyToMany<Vehicle>(x => x.Vehicles) // working fine .Table("wpmember.member_vehicles") .ParentKeyColumn("MEMBER_UID") .ChildKeyColumn("VEHICLE_UID") .Inverse() .Cascade.SaveUpdate() .Cascade.AllDeleteOrphan(); HasMany(x => x.LastUsedVehicleses) //.Table("wpmember.LASTUSED_VEHICLES") .KeyColumn("MEMBER_UID") .Fetch.Select() //.KeyColumns.Add("VEHICLE_UID") //.KeyColumns.Add("MEMBER_UID") .Inverse() .Cascade.AllDeleteOrphan(); } } Vehicle public class VehicleMap : ClassMap<Vehicle> { public VehicleMap() { Table("wpmember.vehicles"); // ... HasManyToMany(x => x.Members) // working fine .Table("wpmember.member_vehicles") .ParentKeyColumn("VEHICLE_UID") .ChildKeyColumn("MEMBER_UID") .Not.LazyLoad() .Cascade.SaveUpdate(); HasMany(x => x.LastUsedVehicles) .KeyColumn("VEHICLE_UID") .Inverse() .Fetch.Select() .Cascade.AllDeleteOrphan(); } } MemberVehicle No mapping - many to many association table LastUsedVehicle public LastUsedVehiclesMap() { Table("wpmember.lastused_vehicles"); CompositeId() .KeyReference(x => x.Vehicle, "VEHICLE_UID") .KeyReference(x => x.Member, "MEMBER_UID"); Map(x => x.DateLastUsed) .Column("DATELASTUSED") .Not.Nullable(); // Things that I tried // References(x => x.Member) // .Fetch.Select() // .Cascade.None() // .Column("MEMBER_UID"); // // References(x => x.Vehicle) // .Fetch.Select() // .Cascade.None() // .Column("VEHICLE_UID"); // Version(x => x.DateLastUsed) // .Column("DATELASTUSED") // .Not.Nullable(); } Classes Member public class Member : PrimaryKeyBase { // ... private readonly Iesi.Collections.Generic.ISet<Vehicle> _vehicles; private Iesi.Collections.Generic.ISet<LastUsedVehicles> _lastUsedVehicles; public Member() { // ... _vehicles = new HashedSet<Vehicle>(); _lastUsedVehicles = new HashedSet<LastUsedVehicles>(); } // GetHashCode public virtual Iesi.Collections.Generic.ISet<Vehicle> Vehicles { get { return _vehicles; } } public virtual void AddVehicle(Vehicle vehicle) { vehicle.AddMember(this); _vehicles.Add(vehicle); } public virtual Iesi.Collections.Generic.ISet<LastUsedVehicles> LastUsedVehicleses { get { return _lastUsedVehicles; } set { _lastUsedVehicles = value; } } } Vehicle public class Vehicle : PrimaryKeyBase { private Iesi.Collections.Generic.ISet<Member> _members; private Iesi.Collections.Generic.ISet<LastUsedVehicles> _lastUsedVehicles; public Vehicle() { _members = new HashedSet<Member>(); _lastUsedVehicles = new HashedSet<LastUsedVehicles>(); } public virtual Member Member { get { return _members.FirstOrDefault(); } } public virtual IEnumerable<Member> Members { get { return _members; } } public virtual void AddMember(Member member) { _members.Add(member); } public virtual void AddLastUsedVehicle(LastUsedVehicles lastUsedVehicles) { lastUsedVehicles.Vehicle = this; lastUsedVehicles.Member = this.Member; _lastUsedVehicles.Add(lastUsedVehicles); } public virtual void ClearLastUsedVehicles() { _lastUsedVehicles.Clear(); } public virtual LastUsedVehicles LastUsedVehicle { get { return _lastUsedVehicles.FirstOrDefault(); } } public virtual IEnumerable<LastUsedVehicles> LastUsedVehicles { get { return _lastUsedVehicles; } } MemberVehicles No Class LastUsedVehicles public class LastUsedVehicles : CompositeKeyBase { public virtual Vehicle Vehicle { get; set; } public virtual Member Member { get; set; } public virtual DateTime DateLastUsed { get; set; } public virtual bool Equals(LastUsedVehicles other) { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; return Equals(other.Vehicle, Vehicle) && Equals(other.Member, Member); } public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; if (obj.GetType() != typeof(LastUsedVehicles)) return false; return Equals((LastUsedVehicles)obj); } public override int GetHashCode() { unchecked { return ((Vehicle != null ? Vehicle.GetHashCode() : 0) * 397) ^ Member.GetHashCode() ^ DateLastUsed.GetHashCode(); } } } Moreover, there's a DB constrain in table LASTUSED_VEHICLES on column vehicle_uid To make it clearer, I'm also attaching some queries and their results // Delete a member delete from member m where account = 'X'; // FAIL - Child record found - The member has vehicles - So makes sense // Delete all vehicles from a member from vehicles table delete from vehicles mv where mv.vehicle_uid = (select mv.vehicle_uid from member_vehicles mv where member_uid = ( select mm.member_uid from member mm where account = 'X')); // // Delete all vehicles from a member from association table delete from member_vehicles mv where member_uid = ( select mm.member_uid from member mm where account = 'X'); // Delete data on LASTUSED_VEHICLES - works delete from LASTUSED_VEHICLES lv where lv.vehicle_uid = (select mv.vehicle_uid from membervehicles mv where member_uid = ( select mm.member_uid from member mm where account = 'X')); Once the table LASTUSED_VEHICLES is empty, I can delete a member --- I can delete all vehicles from a member in this current scenario if LASTUSED_VEHICLES has no data. If it has data, the constraint ism called. try { using (IUnitOfWork unitOfWork = unitOfWorkFactory.Create()) { Member member = nHibernateMemberRepository.GetMemberBySomeMethod(x,y) if (member != null) { if (nHibernateMemberRepository.Delete(unitOfWork, member)) { unitOfWork.Commit(); } } } } catch (Exception) { throw; } The current error I have: SetUp : System.Exception : Attempt to commit during UnitOfWork failed; transaction was rolled back due to the following error: The given key was not present in the dictionary. ----> System.Collections.Generic.KeyNotFoundException : The given key was not present in the dictionary. Sorry for the length of the post but this scenario seems to be quite unique. Thanks for the attention. -- You received this message because you are subscribed to the Google Groups "nhusers" group. To view this discussion on the web visit https://groups.google.com/d/msg/nhusers/-/5BxNJk1TRQwJ. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/nhusers?hl=en.
