通过多对多映射更新记录的问题

时间:2012-12-31 19:08:25

标签: fluent-nhibernate fluent-nhibernate-mapping

我遇到一个问题,我在表结构中有多对多的映射,在尝试编辑简单记录时会产生令人头疼的问题。

我遇到问题的示例布局:

Facilities Many-to-One Locations
Facilities One-to-Many Users
Users Many-to-Many Locations
Users One-to-Many PreviousPasswords

如果我更改了设施记录(更改名称字段),保存后会出现以下错误:

flush()

未处理

集合[Users.PreviousPasswords]

映射看起来像:

public FacilitiesMap()
{
    Table("Facilities");

    Id(x => x.ID);
    Map(x => x.Name);
    HasMany(x => x.Users).KeyColumn("FacilitiesID").Cascade.AllDeleteOrphan().Inverse();
    HasMany(x => x.Locations).KeyColumn("FacilitiesID").Cascade.AllDeleteOrphan().Inverse();
}

public UsersMap()
{
    Table("Users");
    Id(x => x.ID);
    Map(x => x.FirstName);
    Map(x => x.LastName);
    References(x => x.Facilities, "FacilitiesID").ForeignKey("ID");
    HasMany(x => x.PreviousPasswords).KeyColumn("UsersID").Cascade.AllDeleteOrphan().Inverse();
    HasManyToMany<Locations>(x => x.Locations)
         .Schema("Members")
         .Table("UsersToLocations")
         .ParentKeyColumn("UsersID")
         .ChildKeyColumn("LocationsID")
         .LazyLoad()
         .Cascade.SaveUpdate().Inverse();
}

public LocationsMap()
{
    Table("Locations");

    Id(x => x.ID);
    Map(x => x.Name);
    References(x => x.Facilities, "FacilitiesID").ForeignKey("ID");
    HasMany(x => x.Patients).KeyColumn("LocationsID").Cascade.AllDeleteOrphan().Inverse();
    HasManyToMany<Users>(x => x.Users)
         .Schema("Members")
         .Table("UsersToLocations")
         .ParentKeyColumn("LocationsID")
         .ChildKeyColumn("UsersID")
         .Cascade.SaveUpdate();
}

public PreviousPasswordsMap()
{
    Table("PreviousPasswords");

    Id(x => x.ID);
    Map(x => x.Password);
    Map(x => x.DateTime);

    References(x => x.Users, "UsersID").ForeignKey("ID");
}

我能成功更新设施记录的唯一方法是在更改和保存记录之前使用以下功能获取记录:

public Facilities GetFacility(int id)
{
    return FluentSessionManager.GetSession()
        .CreateCriteria<Facilities>()
        .Add(Expression.Eq("ID", id))
        .SetFetchMode("Users", FetchMode.Eager)
        .SetFetchMode("Locations", FetchMode.Eager)
        .UniqueResult<Facilities>();
}

此方法的问题在于,有10,000个用户需要很长时间才能处理此查询。或者更糟糕的是,如果我们还有100个位置,那么需要大约2分钟来编辑一个工厂记录。

我确信Mapping中存在某种问题。不确定如何修复甚至从哪里开始。任何有关这方面的帮助将不胜感激。 提前谢谢。

1 个答案:

答案 0 :(得分:0)

您真的需要该设施的所有用户吗?当您只添加用户时,您可以使用

HasMany(x => x.Users).ExtraLazyLoad();

并在需要真正的所有子集合时改进查询

public Facilities GetFacility(int id)
{
    var session = FluentSessionManager.GetSession();

    // ignore the result, we only want to cache the results in the session
    session.CreateCriteria<Facilities>()
        .Add(Expression.Eq("ID", id))
        .SetFetchMode("Users", FetchMode.Eager)
        .Future<Facilities>();

    return session.CreateCriteria<Facilities>()
        .Add(Expression.Eq("ID", id))
        .SetFetchMode("Locations", FetchMode.Eager)
        .FutureValue<Facilities>().Value;
}