如何在不加载NHibernate中的整个集合的情况下插入项目?

时间:2014-05-02 12:20:45

标签: nhibernate nhibernate-collections

我有一个类似于这样的类模型:

public class TheSystem 
{
    public virtual Guid Id { get; protected set; }
    public virtual ICollection<User> Users { get; protected set; }
}

public class User
{
    public virtual Guid Id { get; protected set; }
    public virtual string Username { get; set; }
    ...
}

映射

public class TheSystemMap : ClassMap<TheSystem>
{
    public TheSystemMap()
    {
        Id(x => x.Id).GeneratedBy.GuidComb();
        HasMany(x => x.Users).Cascade.AllDeleteOrphan().ExtraLazyLoad().Cache.ReadWrite().IncludeNonLazy();

        Cache.ReadOnly();
    }
}

public class UserMap : ClassMap<User>
{
    public UserMap()
    {
        Id(x => x.Id).GeneratedBy.GuidComb();
        Map(x => x.Username).Not.Nullable();
        ...

        Cache.ReadOnly();
    }
}

当我想向系统添加新用户时,问题就出现了。由于我引用了Users集合,NHibernate会加载所有实例(我不想要,因为我只想插入单个用户)。

...
theSystem.Users.Add(new User("aUser"));
...

当我尝试获取项目的计数时,ExtraLazyLoad()选项按预期工作(下一个代码只生成以查询计数)

...
var count = theSystem.Users.Count;
...

我也尝试使用相同的结果添加.AsBag()选项。

我在映射中遗漏了某些内容,或者是一种无法通过常规方式解决的情况?

2 个答案:

答案 0 :(得分:2)

如果您正在做这样的模型,那么您很可能希望拥有一个限制其消费者的API表面,以便他们只能执行有效的操作。当我这样做时,我通常会强制实体完全公开不变。所有改变状态的公共操作都是通过建模可以验证和检查的有效业务操作的方法或对象来调解的。然后是一个受限制较少的内部API,并且可以在此级别直接访问持久性机制。

在此模型中,集合在公共API表面公开为IEnumerable<T>并映射到基础字段,我向相关控制实体添加方法以创建/添加和删除子对象(假设这是一个当然是有效的域操作)。像

这样的东西
theSystem.AddUser(user);

theSystem.RemoveUser(user);

虽然事实上我的添加方法很可能看起来像

theSystem.AddUser(email, password, confirmPassword, firstName, lastName)

因为我不允许API使用者直接构建任何持久化实体。 AddUser方法构造用户,将其保存到会话,并将其添加到Users集合。或者,如果有级联(我通常会避免),只需将其添加到集合中。

(当然,并不能很好地与DI合作,但话说再说那不是我在这里建立的那种API。如果它的DI正在发生,那么下来。)

答案 1 :(得分:1)

您可以创建一个新用户并一起避免TheSystem

User newUser = new User();
session.Save(newUser);