在使用NHibernate修改多对多关系时,防止删除/插入
本文关键字:删除 插入 关系 NHibernate 修改 | 更新日期: 2023-09-27 17:50:34
在我的领域模型中,用户与许多位置相关联-这种关系通过UserPlace类和映射(使用FluentNHibernate)建模,如下所示(用户有一个名为 neighborhood 的UserPlace集合:
public class UserMap : ClassMap<User>
{
HasMany(x => x.Neighbourhood)
.Component(c =>
{
c.Map(x => x.IsDefault).Not.Nullable();
c.Map(x => x.Selected).Not.Nullable().Default("0");
c.References(x => x.Place).Fetch.Join();
}
).Not.LazyLoad().Cascade.SaveUpdate();
}
每当我修改属于一个用户的UserPlace实体,然后将该用户持久化到数据库时,该用户的所有UserPlace行都被删除,然后重新插入。
我认为这是因为NHibernate不知道如何唯一地识别这些行。换句话说,我的映射中的组件没有这样的键。
可以将存储这两个实体之间关系的表中的User_id和Place_id列组合成一个主键。如何使用Fluent设置此密钥?这能解决我看到的删除-重新插入行为吗?
EDIT:我在NHUsers上问过这个问题,Fabio Maulo建议使用IdBag。据我所知,这在Fluent NHibernate中是不支持的——而且组件不允许标识符。我还可以如何映射这种多对多关系并防止"删除全部-重新插入全部"问题?
EDIT 2:以下是NH基于我的映射生成的表
CREATE TABLE [dbo].[User](
[Id] [uniqueidentifier] NOT NULL,
--- a bunch of unimportant fields
CONSTRAINT [PK__User] PRIMARY KEY CLUSTERED ([Id] ASC))
CREATE TABLE [dbo].[Neighbourhood](
[User_id] [uniqueidentifier] NOT NULL,
[IsDefault] [bit] NOT NULL,
[Place_id] [int] NOT NULL,
[Selected] [bit] NOT NULL)
CREATE TABLE [dbo].[Place](
[Id] [int] IDENTITY(1000,1) NOT NULL,
--- a bunch of unimportant fields
CONSTRAINT [PK_Place] PRIMARY KEY CLUSTERED ([Id] ASC))
User之间存在FK关系。我和邻居。User_Id和之间的邻居。Place_id和Place。div Id
您可以像这样映射这种关系,以避免您遇到的情况:
public class UserMap : ClassMap<User>
{
HasMany(x => x.Neighbourhood)
.KeyColumn("User_id")
.Not.LazyLoad().Cascade.SaveUpdate();
}
public class NeighborHoodMap : ClassMap<NeighborHood>
{
Table("Neighbourhood");
CompositeId()
.KeyReference(x => x.User, "User_id")
.KeyReference(x => x.Place, "Place_id");
Map(x => x.IsDefault).Not.Nullable();
Map(x => x.Selected).Not.Nullable().Default("0");
}
邻域类看起来像这样:
public class NeighborHood
{
public virtual User User { get; set; }
public virtual Place Place { get; set; }
public virtual bool IsDefault { get; set; }
public virtual bool Selected { get; set; }
public override bool Equals(object obj)
{
//check here to make sure these objects are equal (user_id and place_id are the same)
}
public override int GetHashCode()
{
return User.Id.GetHashCode() ^ Place.Id.GetHashCode();
}
}
我不熟悉Fluent,但是作为一种变通方法,您可以在UserPlace表上定义一个主键,这样NH就可以跟踪更改。
只是一个想法。