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.

Reply via email to