Fluent NHibernate:单个 table 上的多对多映射
Fluent NHibernate: Many to Many mapping on a single table
我有 Table 家公司,我正试图在它们之间建立一个竞争对手矩阵。
例如:麦当劳是 Wendy's 的竞争对手,反之亦然。
这是我试过的映射:
HasManyToMany(x => x.Competitors)
.ParentKeyColumn("IssuerID")
.ChildKeyColumn("CompetitorID")
.Table("Competitors")
.Cascade.All().Not.LazyLoad();
以及:
Table("Issuer");
Id(x => x.Key).Column("Id").GeneratedBy.Assigned();
Map(x => x.Name).Length(1000);
HasManyToMany(x => x.Competitors).ParentKeyColumn("IssuerID").ChildKeyColumn("CompetitorID").Table("Competitors").Cascade.All().Not.LazyLoad();
当我将竞争对手添加到发行人时,我可以在数据库中看到正确的映射。
所以如果我这样做:
McDonalds.AddCompetitor(Wendys);
我会在数据库中看到正确的数据。当我使用 NHibernate 获得麦当劳时,我还将在实体中看到正确的数据库。
但是,如果我 return 来自 Nhibernate 的 Wendy's 并查看 Competitors 对象:
Wendys.Competitors
我没看到麦当劳。我能理解为什么,因为 Wendy's 是小时候加入麦当劳的。
我该如何修改才能从两个方向查看竞争对手?
我在本地测试中想出了以下解决方案。其实我不是很满意,希望能有更好的支持。也许有。如果有人找到它,请post。
有这样一家店(缩小到竞争对手的相关部分):
public class Store
{
public virtual int Id { get; protected set; }
public virtual IList<Store> Competitors { get; set; }
}
我使用了以下映射(和你一样):
HasManyToMany(x => x.Competitors)
.ParentKeyColumn("Store_Id")
.ChildKeyColumn("Competitor_Id")
.Table("CompetitorsMapping");
如您所说,它不适用于此。但是从 fluentnhibernate 的 Git Repo 中提供的示例来看,它无论如何都包装了列表的添加。
"FirstProject" 示例通过将员工添加到商店来做类似的事情。它首先将商店设置在员工身上,然后将员工添加到商店的员工中(好吧有点不同)。但它会自动处理依赖关系。
所以你可以通过不直接设置而是通过包装添加和删除来解决你的问题(从你的示例代码看起来你已经这样做了):
public class Store
{
public virtual void AddCompetitor(Store competitor)
{
if (!Competitors.Any(x => x.Id == competitor.Id))
{
competitor.Competitors.Add(this);
Competitors.Add(competitor);
}
}
public virtual void RemoveCompetitor(Store competitor)
{
competitor.Competitors.Remove(this);
Competitors.Remove(competitor);
}
}
我特别不喜欢的是对竞争对手的包含检查。不知道它的性能和行为如何。但是如果没有,您可以一遍又一遍地添加相同的竞争对手。使列表变长。
我是 fluentnhibernate 的新手。也许某些设置可以防止自动双重添加。我会对那个设置感兴趣。
我有 Table 家公司,我正试图在它们之间建立一个竞争对手矩阵。
例如:麦当劳是 Wendy's 的竞争对手,反之亦然。
这是我试过的映射:
HasManyToMany(x => x.Competitors)
.ParentKeyColumn("IssuerID")
.ChildKeyColumn("CompetitorID")
.Table("Competitors")
.Cascade.All().Not.LazyLoad();
以及:
Table("Issuer");
Id(x => x.Key).Column("Id").GeneratedBy.Assigned();
Map(x => x.Name).Length(1000);
HasManyToMany(x => x.Competitors).ParentKeyColumn("IssuerID").ChildKeyColumn("CompetitorID").Table("Competitors").Cascade.All().Not.LazyLoad();
当我将竞争对手添加到发行人时,我可以在数据库中看到正确的映射。
所以如果我这样做:
McDonalds.AddCompetitor(Wendys);
我会在数据库中看到正确的数据。当我使用 NHibernate 获得麦当劳时,我还将在实体中看到正确的数据库。
但是,如果我 return 来自 Nhibernate 的 Wendy's 并查看 Competitors 对象:
Wendys.Competitors
我没看到麦当劳。我能理解为什么,因为 Wendy's 是小时候加入麦当劳的。
我该如何修改才能从两个方向查看竞争对手?
我在本地测试中想出了以下解决方案。其实我不是很满意,希望能有更好的支持。也许有。如果有人找到它,请post。
有这样一家店(缩小到竞争对手的相关部分):
public class Store
{
public virtual int Id { get; protected set; }
public virtual IList<Store> Competitors { get; set; }
}
我使用了以下映射(和你一样):
HasManyToMany(x => x.Competitors)
.ParentKeyColumn("Store_Id")
.ChildKeyColumn("Competitor_Id")
.Table("CompetitorsMapping");
如您所说,它不适用于此。但是从 fluentnhibernate 的 Git Repo 中提供的示例来看,它无论如何都包装了列表的添加。
"FirstProject" 示例通过将员工添加到商店来做类似的事情。它首先将商店设置在员工身上,然后将员工添加到商店的员工中(好吧有点不同)。但它会自动处理依赖关系。
所以你可以通过不直接设置而是通过包装添加和删除来解决你的问题(从你的示例代码看起来你已经这样做了):
public class Store
{
public virtual void AddCompetitor(Store competitor)
{
if (!Competitors.Any(x => x.Id == competitor.Id))
{
competitor.Competitors.Add(this);
Competitors.Add(competitor);
}
}
public virtual void RemoveCompetitor(Store competitor)
{
competitor.Competitors.Remove(this);
Competitors.Remove(competitor);
}
}
我特别不喜欢的是对竞争对手的包含检查。不知道它的性能和行为如何。但是如果没有,您可以一遍又一遍地添加相同的竞争对手。使列表变长。
我是 fluentnhibernate 的新手。也许某些设置可以防止自动双重添加。我会对那个设置感兴趣。