Reputation: 4854
I have a class model that looks like this:
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; }
...
}
The mappings
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();
}
}
The problem arrives when I want to add a new user to the system. Because of I'm referencing the Users
collection, NHibernate loads all the instances (which I don't want, because I just want to insert the single user).
...
theSystem.Users.Add(new User("aUser"));
...
The ExtraLazyLoad()
option is working as expected when I try to get the item's count (The code next produces to query only for the count)
...
var count = theSystem.Users.Count;
...
I've also try adding .AsBag()
option with the same result.
I'm missing something in the mapping or is a situation that can't be solved the regular ways?
Upvotes: 2
Views: 711
Reputation: 2518
If you're doing a model like this, chances are you're looking to have an API surface that constrains its consumers so they can only perform valid operations. When I do this, I generally enforce complete public immutability of the entities. All public operations that change state of any kind are mediated through methods or objects modelling valid business actions that can be validated and checked. Then there's an internal API that is less constrained, and direct access to the persistence mechanism is available at this level.
In this model, collections are exposed at the public API surface as IEnumerable<T>
and mapped to the underlying fields, and I add methods to the relevant controlling entities to create/add and remove child objects (provided this is a valid domain operation, of course). Something like
theSystem.AddUser(user);
and
theSystem.RemoveUser(user);
Though in point of fact my add method will most likely look like
theSystem.AddUser(email, password, confirmPassword, firstName, lastName)
since I don't allow API consumers to construct any persisted entity directly. The AddUser
method constructs the user, saves it to the session, and adds it to the Users collection. Or if there's a cascade (which I generally avoid), just adds it to the collection.
(Doesn't work well with DI, of course, but then again that's not the sort of API I'm building here. If there's DI going on it happens lower down.)
Upvotes: 2
Reputation: 15303
You could just create a new User and avoid TheSystem
all together:
User newUser = new User();
session.Save(newUser);
Upvotes: 1