Inheritance with Fluent NHibernate produces double results - nhibernate

I have the following scenario:
public class Login
{
public virtual int Id { get; set; }
public virtual string Username { get; set; }
}
public class User : Login
{
public IList<Account> Accounts { get; set; }
}
If I have two maps (ClassMap<Login> and ClassMap<User>), all queries returns double results - one per maps I'd guess.
Is it possible to avoid this? I don't have a discriminator value. There are a lot more properties on the user, so I'd like to be able to just get a sub set of these via the login.

Since User extends Login, querying Login will, by default, return User instances too.
To avoid this, polymorphism="explicit" must be used in the XML mappings.
For Fluent mappings, use Polymorphism.Explicit().

Perhaps specifying different data tables for the two entities Login and User might do the trick, so you would have to explicitely query either the Login or User depending on your needs. Otherwise, Diego Mijelshon's answer sounds pretty good!

Related

remove from collection without load all collection data. confused which collection mapping to use

I have a many-to-many relationship between Assignment and User
When trying to delete an user from an assignment, I see all users are loaded in the collection.
How to I avoid that?
public class User
{
public virtual int Id { get; private set; }
public virtual IList<Assignment> Assignments { get; set; }
}
public class Assignment
{
public virtual int Id { get; private set; }
public virtual ICollection<User> Users { get; set; }
}
Mappings:
HasManyToMany(user => user.Assignments).Table("UserToAssignment").ParentKeyColumn("UserId").ChildKeyColumn("AssignmentId").Inverse().ExtraLazyLoad();
HasManyToMany(productAssignment => productAssignment.Users).AsSet().Table("UserToAssignment").ParentKeyColumn("AssignmentId").ChildKeyColumn("UserId").LazyLoad();
Calling code:
assignment.Users.Remove(user)
Initially I used Bag instead of Set for Assignment mapping, but when updating it, it was deleting and then reinserting alot of rows in the AssignmentsToUsers table. So I changed to using Set.
But now I see a problem with using Set: it brings all data in memory.
What is the recommended way of doing this?
You can't avoid this and I would ignore it if performance is acceptable. If performance is a problem, there are three ways I can think of to tackle it:
If the other side of the collection (User.Assignments) is lighter weight then remove the assignment from the user instead.
Model the many-to-many table and delete the object directly. You would have to be certain that the Users collection is not going to be loaded prior to this because the in-memory representation will still contain the deleted record.
Direct delete using SQL -- this has the same caveat as #2.
You should use extra lazy mode also for Assignment.Users.

How to create a NHibernate proxy object with some initiliazed fields (other than Id)?

I want to create an object proxy, similar to what ISession.Load is returning, but with some fields initialized. For other properties, when accessed, the proxy will fetch the entire object from database.
Consider the following example:
public class User
{
protected User() {
}
public User(int id, string username, string email) {
// ...
}
// initialize the following fields from other datasources
public virtual int Id { get; set; }
public virtual string UserName { get; set; }
public virtual string Email { get; set; }
// the rest of fields when accessed will trigger a select by id in the database
public virtual string Field1 { get; set; }
public virtual string Field2 { get; set; }
public virtual DateTime Field3 { get; set; }
public virtual ISet<Comment> Comments { get; set; }
}
The Id, UserName, Email are well-known in my case, so I could create an object proxy containing these fields, and for the others leave the default proxy behavior. In addition to throwing an exception if this id is not found in the database, i could throw an exception if preinitialized fields do not match or overwrite them silently. I am using NHibernate.ByteCode.Castle for proxy factories.
Edit:
The purpose for this is to be able to have some projection properties from an entity which can be queried elsewhere (say. a lucene index) and to avoid database calls. Then instead of wrapping these fields in a custom component class containing only these subset of properties, I want to use the proxy object directly so that I am able to load the rest of fields if needed. In the best case scenario I wouldn't hit the database at all, but in some corner cases I'd like to access other fields, too. The SELECT N+1 problem's impact can be greatly reduced by using batching.
An hypothetical version of code I want to use would be:
// create User object proxy with some fields initialized
var user = Session.Load<User>(5, new { UserName = "admin", Email = "admin#company.com" });
Console.WriteLine(user.Id); // doesn't hit the database
Console.WriteLine(user.UserName); // doesn't hit the database
Console.WriteLine(user.FullName); // doesn't hit the database
if (somecondition) {
Console.WriteLine(user.Field1); // fetches all other fields
}
You can specify an eager fetch inside the query to actually retrieve the needed associations. This could be done in different ways depending on what query style ( Criteria,Hql or LINQto NH ) you are using. But the key is changing the fetch mode.
for non-collection properties, I wouldn't do that;
the cost of prefetching them from the DB when you load your entity is (usually) so small that I wouldn't even bother.
for collection properties, just mark the collection fetch strategy as 'lazy=true'.
The only case where I would think about doing something like that is when I have a very large number of properties which I don't need (in your example- say Field1..Field20).
In that case I would either:
1. Define those properties together as a component, or
2. create a DTO for fetching only a subset of your entity's properties.
specifying lazy = "true" (or Not.LazyLoad() for Fluent NHib) on properties Field1, Field2, Field3, Comments mappings may help, though not sure about Select N+1 issue.
another way to go is specifying lazy = "false" for UserName, Email

How can I model this object hierarchy in Fluent NHibernate without violating DDD principles?

I am trying to build a domain model that will allow me to manage Contracts.
The Contract class is my aggregate root, and it has a single property right now, which is Reviewers.
Reviewers, in the context of the Contract, each have a property to it's parent Contract, and a First Name, Last Name, and Login. The reason they have these properties is so I can have the user select which Reviewers they want on a Contract.
The database that I'm tying my domain model to already exists, and it's a legacy system that I'm trying to extend.
It has a Contract Table, and a Reviewer Table.
The thing I haven't mentioned up until this point, is that Reviewers are actually Users in the system. So there's actually a third table involved, which is Users.
I have been able to map my Contract Table easily with FNH.
It looks something like this:
public class ContractMapping: ClassMap<Contract>
{
public ContractMapping()
{
Id(c => c.Id);
HasMany(c => c.AdditionalReviewers);
}
}
But I'm not sure how to model my Reviewers, because they are in fact Users as well. So my object model looks like this:
public class Reviewer: User
{
public virtual Guid Id { get; set; }
public virtual Contract Contract { get; set; }
}
public class User
{
public virtual Guid Id { get; set; }
public virtual string Login { get; set; }
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }
}
I've been able to map my User class properly, and it looks something like this:
public class UserMapping: ClassMap<User>
{
public UserMapping()
{
Id(u => u.Id);
Map(u => u.Login);
Map(u => u.FirstName);
Map(u => u.LastName);
}
}
and I believe I want to map my Reviewer class like this:
public class ReviewerMapping: SubclassMap<Reviewer>
{
public ReviewerMapping()
{
Table("Reviewer");
//Id(r => r.Id).Column("ReviewerId"); <- won't compile
References(r => r.Contract).Column("ContractId");
}
}
So the problem I'm having is this:
The relationship between the User table and the Reviewer table is one to many. Meaning, for a given User there may be many Reviewer records. Why? Because a User has to be a Reviewer for a specific Contract. This causes an issue with the mapping, though, because the primary key for my Reviewer and the primary key for my User are completely different values, by necessity.
Also, because of the way I'm using Reviewer, when I create a new Reviewer, what I'm really trying to do is to associate a User with a Contract. I am not trying to create an entirely new User in the database.
What is the correct way for me to map Reviewer, knowing that in my domain model it is a subclass of User?
Sounds like a the Reviewer is not really modelling a person, but modelling a role or assignment the User takes on. I'd say your domain model is flawed in this aspect. Tweak Reviewer to be an association class between a User and a Contract.
I don't think Reviewer should inherit from User in the scenario you've described. I would have the Reviewer class hold a User object instead (composition over inheritance).
If it helps you conceptualize it better, rename Reviewer to Review. That way you can stop thinking about it as a User since it really isn't (multiple Reviewers in your current domain can be the same User, which doesn't make much sense).

Question about Repositories and their Save methods for domain objects

I have a somewhat ridiculous question regarding DDD, Repository Patterns and ORM. In this example, I have 3 classes: Address, Company and Person. A Person is a member of a Company and has an Address. A Company also has an Address.
These classes reflect a database model. I removed any dependencies of my Models, so they are not tied to a particular ORM library such as NHibernate or LinqToSql. These dependencies are dealt with inside the Repositories.
Inside one of Repositories there is a SavePerson(Person person) method which inserts/updates a Person depending on whether it already exists in the database.
Since a Person object has a Company, I currently save/update the values of the Company property too when making that SavePerson call. I insert / update all of the Company's data - Name and Address - during this procedure.
However, I really have a hard time thinking of a case where a Company's data can change while dealing with a Person - I only want to be able to assign a Company to a Person, or to move a Person to another Company. I don't think I ever want to create a new Company alongside a new Person. So the SaveCompany calls introduce unnecessary database calls. When saving a Person I should just be able to update the CompanyId column.
But since the Person class has a Company property, I'm somewhat inclined to update / insert it with it. From a strict/pure point of view, the SavePerson method should save the entire Person.
What would the preferred way be? Just inserting/updating the CompanyId of the Company property when saving a Person or saving all of its data? Or would you create two distinct methods for both scenarios (What would you name them?)
Also, another question, I currently have distinct methods for saving a Person, an Address and a Company, so when I save a Company, I also call SaveAddress. Let's assume I use LinqToSql - this means that I don't insert/update the Company and the Address in the same Linq query. I guess there are 2 Select Calls (checking whether a company exists, checking whether an address exists). And then two Insert/Update calls for both. Even more if more compound model classes are introduced. Is there a way for LinqToSql to optimize these calls?
public class Address
{
public int AddressId { get; set; }
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
public string City { get; set; }
public string PostalCode { get; set; }
}
public class Company
{
public int CompanyId { get; set; }
public string Name { get; set; }
public Address Address { get; set; }
}
public class Person
{
public int PersonId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public Company Company { get; set; }
public Address Address { get; set; }
}
Edit
Also see this follow up question. How are Value Objects stored in a Database?
I myself have used the IRepository approach lately that Keith suggests. But, you should not be focusing on that pattern here. Instead, there are a few more pieces in the DDD playbook that can be applied here.
Use Value Objects for your Addresses
First, there is the concept of Value Objects (VO) you can apply here. In you case, it would be the Address. The difference between a Value Object and an Entity Object is that Entities have an identity; VOs do not. The VO's identity really is the sum of it's properties, not a unique identity. In the book Domain-Drive Design Quickly (it's also a free PDF download), he explains this very well by stating that an address is really just a point on Earth and does not need a separate SocialSecurity-like identity like a person. That point on Earth is the combination of the street, number, city, zip, and country. It can have latitude and longitude values, but still those are even VOs by definition because it's a combination of two points.
Use Services for combining your entities into a single entity to act upon.
Also, do not forget about the Services concept in the DDD playbook. In your example, that service would be:
public class PersonCompanyService
{
void SavePersonCompany(IPersonCompany personCompany)
{
personRepository.SavePerson();
// do some work for a new company, etc.
companyRepository.SaveCompany();
}
}
There is a need for a service when you have two entities that need both need a similar action to coordinate a combination of other actions. In your case, saving a Person() and creating a blank Company() at the same time.
ORMs usualyl require an identity, period.
Now, how would you go about saving the Address VO in the database? You would use an IAddressRepository obviously. But since most ORMs (i.e. LingToSql) require all objects have an Identity, here's the trick: Mark the identity as internal in your model, so it is not exposed outside of your Model layer. This is Steven Sanderson's own advice.
public class Address
{
// make your identity internal
[Column(IsPrimaryKey = true
, IsDbGenerated = true
, AutoSync = AutoSync.OnInsert)]
internal int AddressID { get; set; }
// everything else public
[Column]
public string StreetNumber { get; set; }
[Column]
public string Street { get; set; }
[Column]
public string City { get; set; }
...
}
From my recent experience of using the repository pattern I think you would benefit from using a generic repository, the now common IRepository of T. That way you wouldn't have to add repository methods like SavePerson(Person person). Instead you would have something like:
IRepository<Person> personRepository = new Repository<Person>();
Person realPerson = new Person();
personRepository.SaveOrUpdate(realPerson);
This method also lends itself well to Test Driven Development and Mocking.
I feel the questions about behavior in your description would be concerns for the Domain, maybe you should have an AddCompany method in your Person class and change the Company property to
public Company Company { get; private set; }
My point is; model the domain without worrying about the how data will be persisted to the database. This is a concern for the service that will be using your domain model.
Back to the Repository, have a look at this post for good explanation of IRepository over LinqToSql. Mike's blog has many other posts on Repositories. When you do come to choose an ORM I can recommend HHibernate over LinqToSql, the latter is now defunct and NHibernate has a great support community.

NHibernate N+1 select : architectural solution?

Considering the following "database" :
Post -> User
The entities :
class User
{
public virtual string Name { get; set; }
public virtual IList<Post> Posts { get; set; }
}
class Post
{
public virtual string Title { get; set; }
public virtual User Author { get; set; }
}
And the following service Layer:
class UserService
{
IRepositoryUsers repositoryUsers;
IList<User> GetUsers()
{
return this.repositoryUsers.GetAllUsers();
}
}
When I want to print all users, with associated post count, I get (no surprise here) a N+1 select problem, as for each line, it will create a select to get the posts for the users.
Now here is my question : what is the "best" way to handle this, as there are some cases when I don't want to eager load each user's posts.
Should I create as many methods in my repository (and service) to match those scenarios ?
In general, there's a few ways to get rid of a Select N+1 problem. With NHibernate, one of my favorite ways to do this is to use the Criteria API, which is very sensible and well thought-out.
session.CreateCriteria(typeof(Fruit)) // Get me some fruit.
.SetFetchMode("CitrusType", FetchMode.Eager) // Just get this one field.
.Add(Expression.Eq("Basket", 47)) // Only fruit that are in this basket.
.List(); // Get 'em all.
To read more about this and other strategies, I recommend a look at this interesting blog post.
One thing you could do is to have a fetching strategy for every scenario in which you need to retrieve the data.
This blog post explains a possible solution for this type of problem, the author uses his own version of IRepository but you use the same ideas in your repository (or check out his NCommon project to get some inspiration)