我有一个错误,无论我用多少谷歌搜索它,我都找不到修复它。我已阅读并尝试使用以下主题来解决它。这些是我发现的与我的问题最接近的:
数据库架构
我的映射涉及四个表:Member
、Vehicle
和。MemberVehicles
LastUsedVehicles
- 表
Member
和Vehicle
是应用程序中的业务对象。 - 表是一个没有额外列
MemberVehicles
的关联表 ( )。many-to-many
这种关系没有问题。 - 表
LastUsedVehicles
有一个由Vehicle_uid
和组成的组合键Member_uid
,它们是对应表的外键。该表还有一个额外的DateLastUsed
列来存储时间戳。 这个表的映射是我的问题。
问题
当我删除 aMember
时,我Vehicle
还需要删除他的LastUsedVehicles
所有工作)。
当我执行此代码时...
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;
}
...我收到此错误:
System.Exception:在 UnitOfWork 期间尝试提交失败;由于以下错误,事务被回滚:字典中不存在给定的键。----> System.Collections.Generic.KeyNotFoundException :字典中不存在给定的键。
LastUsedVehicles
当表为空时,我没有收到错误消息。
映射
成员
public class MemberMap : ClassMap<Member>
{
public MemberMap()
{
Table("member");
HasManyToMany<Vehicle>(x => x.Vehicles) // working fine
.Table("member_vehicles")
.ParentKeyColumn("MEMBER_UID")
.ChildKeyColumn("VEHICLE_UID")
.Inverse()
.Cascade.SaveUpdate()
.Cascade.AllDeleteOrphan();
HasMany(x => x.LastUsedVehicleses)
//.Table("LASTUSED_VEHICLES")
.KeyColumn("MEMBER_UID")
.Fetch.Select()
//.KeyColumns.Add("VEHICLE_UID")
//.KeyColumns.Add("MEMBER_UID")
.Inverse()
.Cascade.AllDeleteOrphan();
}
}
车辆
public class VehicleMap : ClassMap<Vehicle>
{
public VehicleMap()
{
Table("vehicles");
HasManyToMany(x => x.Members) // working fine
.Table("member_vehicles")
.ParentKeyColumn("VEHICLE_UID")
.ChildKeyColumn("MEMBER_UID")
.Not.LazyLoad()
.Cascade.SaveUpdate();
HasMany(x => x.LastUsedVehicles)
.KeyColumn("VEHICLE_UID")
.Inverse()
.Fetch.Select()
.Cascade.AllDeleteOrphan();
}
}
最后使用的车辆
public class LastUsedVehiclesMap : ClassMap<LastUsedVehicles>
{
public LastUsedVehiclesMap()
{
Table("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();
}
}
课程
成员
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; }
}
}
车辆
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; }
}
}
最后使用的车辆
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();
}
}
}
调试信息
为了更清楚,我还附上了一些 SQL 查询及其结果。
// 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'));
一旦表LASTUSED_VEHICLES
为空,我可以删除一个成员。
很抱歉帖子的长度,但这种情况似乎很独特。感谢您的关注。