2

我有一个看起来像这样的类模型:

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()具有相同结果的选项。

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

4

2 回答 2

2

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

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

theSystem.AddUser(user);

theSystem.RemoveUser(user);

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

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

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

(当然,DI 不能很好地工作,但话又说回来,这不是我在这里构建的那种 API。如果有 DI,它会发生在更低的位置。)

于 2014-05-06T15:23:07.303 回答
1

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

User newUser = new User();
session.Save(newUser);
于 2014-05-02T17:05:45.520 回答