hydrate in nhibernate? - nhibernate

what is hydrate in nhibernate? I am not able to get my head around this term.
This was used, in a video, in context of hydrating the child table rows.
Please advise.
Thanks
AJ

You may wish to look at Build Your own DAL. It has a section on hydration that you probably will find interesting.
But hydration from a really simple view means means take from the raw persistent storage module and map into an object/a list of objects.
Update
Look at Understanding Lazy Loading Strategies or Lazy Loading - Eager Loading. I think this is what is happening for the hydration of the objects in the video you describe.
Example
This is a really simple hydration example (Not an NHibernate example)
Say we have run a query like: select name, breed from tblDogs and that has these results
K9, GermanShepard
IBeBlind, Labrador
SmallAnoyance, Shitsu
Trigger, GermanShepard
And say we have the following object:
public class Dog {
public string name { get; set; }
public string breed { get; set; }
}
Now we can write our own hydrator:
public List<Dog> Hydrate(results rs) {
List<Dog> dogs = new List<Dog>();
foreach(Record rec in rs) {
Dog d = new Dog();
d.name = rec["name"];
d.breed = rec["breed"];
dogs.Add(d);
}
return dogs;
}

Related

NHibernate 4 child collection saved, but not re-loaded

I've got an NHibernate 4 project with several collection relationships. I'm unit-testing the object model, exercising all the collections. Most work fine, but in one case, the child collection is cascade-saved properly, but on loading the parent entity and examining the collection property, the child collection is empty.
Here are the abbreviated classes. GatewayUser is the parent object, and it has a collection of Student. The collection has a private backing property, and AddStudent/RemoveStudent methods.
Further complications: I'm using the NHibernate.AspNet.Identity library for OAuth2 user management, and GatewayUser inherits from IdentityUser. That in turn inherits from the the library's internal base entity class, which is different from my project's own base class.
public class GatewayUser : IdentityUser
{
public GatewayUser()
{
}
public virtual string FirstName { get; set; }
// ...More value properties and OAuth stuff omitted
// students associated with this user
private IList<Student> _students = new List<Student>();
public virtual IList<Student> Students
{
get { return new ReadOnlyCollection<Student>(_students); }
}
public virtual GatewayUser AddStudent(Student s)
{
if (_students.Contains(s))
return this;
s.GatewayUser = this;
_students.Add(s);
return this;
}
public virtual GatewayUser RemoveStudent(Student s)
{
if (_students.Contains(s))
{
_students.Remove(s);
}
return this;
}
Student is more ordinary; it inherits from my own BaseEntity class, has many value properties, and its own child collection of ProgramApplication items. Interestingly, this collection saves and loads fine; it's got the same structure (private backer, etc.) as the failing collection in GatewayUser.
The mapping is complicated, because the library internally maps its classes with NHiberante.Mapping.ByCode.Conformist classes (which I have no prior experience with).
I'm mapping my own classes with NHibernate automapping, because I have so many classes and properties to map. To get it all working, I copied the library's mapping helper class, and modified it a bit to add my base entity classes to it's list called baseEntityToIgnore. I also had to create a conformist mapping for GatewayUser, since it has a different base entity type, and my automapping wouldn't pick it up.
The unit test looks like this:
[Test]
public void GatewayUserCascadesStudents()
{
var u = new GatewayUser() { FirstName = "Mama", LastName = "Bear", UserName = "somebody#example.com" };
var s1 = new Student() { FirstName = "First", LastName = "Student" };
var s2 = new Student() { FirstName = "Second", LastName = "Student" };
u.AddStudent(s1).AddStudent(s2);
using (var s = NewSession())
using (var tx = s.BeginTransaction())
{
s.Save(u);
tx.Commit();
}
GatewayUser fetched = null;
int count = 0;
using (var s = NewSession())
{
fetched = s.Get<GatewayUser>(u.Id);
count = fetched.Students.Count;
}
Assert.AreEqual(2, count);
}
The generated SQL inserts into both AspNetUsers and GatewayUser (reflecting the inheritance relationship), and inserts two records into Student. All good. On fetching, the SELECT joins the two user tables, and I get a GatewayUser object, but accessing the Students collection does not trigger a SELECT on the Student table. But if I change the mapping to Lazy(CollectionLazy.NoLazy), the SQL to select eagerly load Students appears in the log, but the collection is not populated. If I switch the database from SQLite to Sql Server, I see the student records in the table. The generated SQL (when NoLazy is applied) will fetch them. So on the database end, things look fine.
I have to think my Frankenstein mapping situation is to blame. I'm mixing the library's conformist mapping with Fluent mapping, and there are two different base entity classes. However, the generated schema looks correct, and the save cascades correctly, so I don't know if that's the issue.
Found my own answer. My mapping of the parent class's list was like this:
public class GatewayUserMap : JoinedSubclassMapping
{
public GatewayUserMap()
{
Key(g => g.Column("Id"));
Property(c => c.FirstName, m => m.Length(50));
// ... more properties
List(gu => gu.Students, map =>
{
map.Key(c => c.Column("GatewayUser_Id"));
map.Cascade(Cascade.All | Cascade.DeleteOrphans);
map.Index(li => li.Column("ListIndex"));
map.Access(Accessor.Field | Accessor.NoSetter);
}
);
}
}
I have a private backing field for the collection. Removing Accessor.NoSetter from the collection mapping fixed it. In fact, it still worked without Accessor.Field -- I guess the mapper does a good job of looking around for one, and using it if found. Changing the name of the private backer from "_students" to "funnyName" prevented the mapper from finding it.

Object mapper vs Object wrapper

I would appreciate a little help here...
Lets say that in an application we have a Data Layer and a Business Logic Layer. In the DAL we have the following entity:
public class Customer {
public string Name {get; set;}
public ICollection<Address> Addresses {get; set;}
}
public class Address {
public string Street {get; set;}
}
In the BLL we have the following POCOs:
public class CustomerDto {
public string Name {get; set;}
public ICollection<AddressDto> Addresses {get; set;}
}
public class AddressDto {
public string Street {get; set;}
}
The entities in the DAL are populated with a ligth-weight ORM and retrieve from the BLL using a repository. Ex:
public class CustomerInformationService {
private readonly ICustomerRepository _repository {get; set;}
public CustomerInformationService (ICustomerRepository repository)
{
_repository = repository;
}
public class CustomerDto Get(int id)
{
var customerEntity = _repository.Get(id);
var customerDto = /* SOME TRANSFORMATION HERE */
return customerDTO;
}
}
My questions is about the /* SOME TRANSFORMATION HERE */ part. There is a discussion in our team about how to do the "mapping".
One approach is to use a mapper either an automapper or a manual mapping.
The second approach is to use sort of like a wrapper around Entity and reference the DTO in order to save a copying operation between object. Something like this:
public class CustomerDto
{
private IEntity _customerEntity;
public IEntity CustomerEntity { get {return _customerEntity;}}
public CustomerDto(IEntity customerEntity)
{
_customerEntity = customerEntity;
}
public string Name
{
get { return _customerEntity.Name; }
}
public ICollection<Address> Addresses
{
get { return _customerEntity.Addresses; }
}
}
The second approach feels a little weird to me because _customerEntity.Addresses feels like a leak (_customerEntity's reference) between my DAL and my BLL but I am not sure.
Are there any advantages/disavantages of using one approach over the other one?
Additional info: We usually pull a max. of 1000 records at a time that would need to be transform between Entity and DTO.
You did not mentioned your "ligth-weight ORM". I will answer in two sections.
If you are using ORM that creates proxies
You should avoid exposing Entities outside certain boundary. ORMs like NHibernate/EF implement lazy loading based on proxies. If you expose Entities to application/UI layer, you will have little control over ORM behavior. This may lead to many unexpected issues and debugging will also very difficult.
Wrapping Entities in DTOs will gain nothing. You are accessing Entities anyway.
Using DTOs and mapping them with some mapper tool like AutoMapper is good solution here.
If you are using ORM that does not create proxies
Do NOT use DTOs, directly use your Entities. DTOs are useful and recommended here in many cases. But the example you given in question does not need DTOs at all.
In case you choose to use DTOs, wrapping Entities in DTOs does not make sense. If you want to use Entity anyway, why wrap it? Again, tool like AutoMapper could help.
Refer this question. It's bit different; I am asking Yes/No and you are asking How. But still it will help you.
I bet for the service layer approach. Basically because something that looks like a business object or domain object has nothing to do with DTOs.
And, indeed, you and your team should use AutoMapper instead of repeating the same code tons of times which will consist in setting some properties from A to B, A to C, C to B...

Can NHibernate query for specific children without lazy loading the entire collection?

When I have an entity object with a one-to-many child collection, and I need to query for a specific child object, is there a feature or some clever pattern I haven't come up with yet to avoid that NHibernate fetches the entire child collection?
Example:
class Parent
{
public virtual int Id { get; proteced set; } // generated PK
public virtual IEnumerable<Child> Children { get; proteced set; }
}
class Child
{
public virtual int Id { get; protected set; } // generated PK
public virtual string Name { get; protected set; }
public virtual Parent Parent { get; protected set; }
}
// mapped with Fluent
class Service
{
private readonly ISessionFactory sessionFactory;
public Service(ISessionFactory sessionFactory)
{
this.sessionFactory = sessionFactory;
}
void DoSomethingWithChildrenNamedBob(int parentId)
{
using(var session = sessionFactory.OpenSession())
{
var parent = session.Get<Parent>(parentId);
// Will cause lazy fetch of all children!
var childrenNamedBob = parent.Children.Where(c => c.Name == "Bob");
// do something with the children
}
}
}
I know it's not the best example because in this case one would probably just query the Child entities directly, but I have encountered situations where I already had a Parent object and needed to traverse specific sub-trees through it.
Short answer: no. Longer answer: you can make it do this, with some sleight of hand.
Rippo's answer above shows how you would do it the 'proper' NHibernate way (whether it's with Linq or QueryOver or HQL doesn't really matter - the point is you have to step outside the parent -> child relationship to do a query). You can take this a step further and disguise this behind a façade. But to do so, you have to remove the mapped relationship entirely and replace it with a query at all times. You'd take out the Parent -> Children mapping, but leave the Child -> Parent mapping intact; then re-write the property on Parent to look like this:
public virtual IQueryable<Child> Children
{
get
{
// somehow get a reference to the ISession (I use ambient context), then
return session.Query<Child>().Where(c => c.Parent == this);
}
}
Now, when you use Parent.Children you get back a queryable collection, so you could then write
IEnumerable<Child> childrenNamedBob = parent.Children.Where(c => c.Name == "Bob");
The only way you could do this and preserve the mapping is to amend NHibernate's collection objects (or inject your own). Diego Mijelshon (who is around these parts) wrote a spike of exactly that, adding IQueryable support to NHibernate collections so you could do
IEnumerable<Child> childrenNamedBob = parent.Children.AsQueryable().Where(c => c.Name == "Bob");
But from what I can see, this never went any further and there's no apparent plan to add this capability to NH. I have run Diego's code and it does work, but obviously it's not production quality and hasn't been tested, and I don't think it's ever been officially 'released' even as a private patch.
Here's the link to the discussion on the NH issue tracker: https://nhibernate.jira.com/browse/NH-2319
I believe NH should support this out of the box, as it's a natural way for most .NET devs to want to interact with pretty much anything enumerable, now that we have Linq, and not being able to do it without the side-effect of loading an unbounded collection into RAM sucks. But the traditional NH model is session -> query and that's what 99% of people use.
I asked the same question on NHusers a few weeks ago and didn't get an answer so I suspect the answer is you will always get all the parents children and then perform a in-memory filter. In many cases this might be the correct way in seeing it.
In your case I would rewrite the query to be:-
var childrenNamedBob = session.Query<Children>()
.Where(w => w.Parent.Id == parentId && w.Name == "Bob");
Then simply to get parent (if childrenNamedBob has results) you could call:-
var parent = childrenNamedBob.First().Parent;
or as you rightly pointed out:-
var parent = session.Get<Parent>(parentId);
You can now do that with NHibernate 5 directly without specific code !
See https://github.com/nhibernate/nhibernate-core/blob/master/releasenotes.txt
Build 5.0.0
=============================
** Highlights
...
* Entities collections can be queried with .AsQueryable() Linq extension without being fully loaded.
...

Do I have to implement Add/Delete methods in my NHibernate entities?

This is a sample from the Fluent NHibernate website:
Compared to the Entitiy Framework I have ADD methods in my POCO in this code sample using NHibernate. With the EF I did context.Add or context.AddObject etc... the context had the methods to put one entity into the others entity collection!
Do I really have to implement Add/Delete/Update methods (I do not mean the real database CRUD operations!) in a NHibernate entity ?
public class Store
{
public virtual int Id { get; private set; }
public virtual string Name { get; set; }
public virtual IList<Product> Products { get; set; }
public virtual IList<Employee> Staff { get; set; }
public Store()
{
Products = new List<Product>();
Staff = new List<Employee>();
}
public virtual void AddProduct(Product product)
{
product.StoresStockedIn.Add(this);
Products.Add(product);
}
public virtual void AddEmployee(Employee employee)
{
employee.Store = this;
Staff.Add(employee);
}
}
You don't have to do this for nhibernate, you have to do this for keep in-memory consistence and not repeat yourself.
Consistence in memory
If you have a two way relationship, lets say Order has Lines, and Line as a relationship to order. You don't want to have a reference from one side and not from the other.
If you just do:
order.Lines.Add(line);
You have made a reference from Order to Line, but Line.Order property remains null. So your in-memory instances are not consistent.
Don't Repeat Yourself
You can use the following code :
order.Lines.Add(line);
line.Order = order;
but you will be repeating yourself, so it is better to put this code in only one place, and the best place is as order.AddLine(..).
You don't have to. You could just call SomeStore.Products.Add(someProduct) directly from outside of your entity. But it's often good practice to make the collections 'read-only' from a public perspective, and using an add method in the entity for adding items.
One benefit of this is that you can put additional logic in there. For instance in your store example, you could set a 'storesStockedIn' collection (if there was such a thing) in the same method, and so keep all the logic about to creating that relationship in one place.
This isn't really a NHibernate thing, but rather an OOP thing. (Although I'm not familiar with EF - maybe it automates some of this for you). The design decisions are exactly the same as if it was just an unpersisted poco (without NHibernate).

nhibernate one-to-many collection- retrieve only the superclass

I have the following classes:
class Person
{
public string Name { get; set; }
}
class Employee : Person
{
public int Salary { get; set; }
}
class Company
{
public IList<Person> PeopleWhoAreNotEmployees { get; set; }
}
Person and Employee are mapped using table-per-class-heirarchy strategy.
When I retrieve the PeopleWhoAreNotEmployees collection, I want it only to contain elements that are Person, and NOT Employees.
How can I (fluently) configure the collection to only retrieve elements of the super class?
I think it's something to do with the Polymorphism property, but I couldn't really figure out how to do that.
thanks,
Jhonny
EDIT:
following the discussion with Jamie, I feel I need to clarify that the case here isn't really Person and Employee, but more like Employee and HistoricalEmployee.
Meaning- when an employee 'dies', they're not really deleted, but they become HistoricalEmployee (with a few more attributes, such as termination date etc.).
Obviously, over time, the number of HistoricalEmployees will exceed the number of Employees by magnitudes, so I can't fetch all HistoricalEmployees when I only need current Employees.
Sorry for the ambigiuity of the original question...
J
P.S. I didn't change the original question since it would make the answer irrelevant. a new version of this question is available here
I don't think you can, but that's not how I would approach it anyway. I would use a private field for the collection and expose methods that filter the list. This is much easier to map and work with and performance will be fine if the collection is reasonably sized (I don't know what's reasonable but I wouldn't worry about it if it's < 1000). It would make it easier if you had an abstract PersonBase class that both Person and Employee extend so that you don't have to deal with uncertainty that a Person might be an Employee.
public class Company
{
private IList<Person> _allPeople;
public IEnumerable<Employee> Employees()
{
return _allPeople.OfType<Employee>();
}
public IEnumerable<Person> PeopleWhoAreNotEmployees()
{
return _allPeople.Where(x => !(x is Employee));
}
}
EDIT:
In response to your comment, the filtering would take place in the class. The private collection would cause all the People to be loaded, and the properties would dynamically filter that collection. The mapping wold look like:
public class CompanyMap : ClassMap<Company>
{
public CompanyMap ()
{
// only collection is shown w/o cascade option
HasManyToMany(x => x.Person).Access.CamelCaseField(Prefix.Underscore);
}
}
what I ended up doing was using a 'where' clause on my property.
the fluent configuration looks like so:
mapping.HasMany(x => x.Employees)
.Where("IsFired = 0")