nHibernate - Fetch with private collection - nhibernate

Is there a way to use Fetch with collection that is private?
This is what i have for code:
public class Owner
{
private ICollection<Cat> _cats = new List<Cat>();
public virtual int Id { get; set; }
public virtual IEnumerable<Cat> Cats { get { return _cats; } }
public virtual void AddCat(Cat cat) { ... }
}
public class Cat
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual Owner Owner { get; set; }
}
Most of the time, I want to lazy load the Cats collection, but sometimes I don't. I want to use Fetch in a Linq query to eager load it. I currently get a "could not resolve property: Cats..." exception. I am assuming I get this because I have a Set("_cats", ...) in my ClassMapping, and its looking for the property Cats to be mapped. Is there a way to get Fetch to work with the private collection of Cats?

NHibernate generates proxies from your objects, when they are loaded from database, so the properties you want to map must be virtual. You should make your private cats collection protected virtual and try again. I only mapped properties with a protected setter and a public getter, but this solution may be suitable with full protected properties, too.

You need to specify nosetter access strategy in property mapping.
Take a look at this answer for details: Domain Model with Nhibernate design issue

Related

How to map and reference entities from other data sources with NHibernate

I'm currently working on and ASP.NET MVC application in which I have a User entity like follows:
public class User
{
public virtual int Id { get; protected set; }
public virtual string Name { get; protected set; }
public virtual string Role { get; protected set; }
public virtual Location Location { get; protected set; }
}
Where location is just as straightforward:
public class Location
{
public virtual string Id { get; protected set; }
public virtual string Building { get; protected set; }
public virtual string City { get; protected set; }
public virtual string Region { get; protected set; }
}
My complication arises because I want to populate the User from Active Directory and not the database. Additionally, several classes persisted to the database reference a user as a property. I've got an ADUserRepository for retrieval, but I don't know how to integrate these Users into my object graph when the rest is managed by NHibernate.
Is there a way for NHibernate to persist just an id for a User without it being a foreign key to a Users table? Can I map it as a component to accomplish this? I've also looked at implementing IUserType to make the translation. That way it would map to a simple field and ADUserRepository could be put in the chain to resolve the stored Id. Or am I trying to hack something that's not really feasible? This is my first time around with NHibernate so I appreciate any insight or solutions you can give. Thanks.
Update
It appears my best solution on this will be to map the User with an IUserType and inject (preferably with StructureMap) a service for populating the object before its returned. Framed in that light there are a couple of questions here that deal with the topic mostly suggesting the need for a custom ByteCodeProvider. Will I still need to do this in order for IUserType to take a parameterized constructor or do the comments here: NHibernate.ByteCode.LinFu.dll For NHibernate 3.2 make a difference?
using a Usertype to convert user to id and back
public class SomeClass
{
public virtual string Id { get; protected set; }
public virtual User User { get; protected set; }
}
// in FluentMapping (you have to translate if you want to use mapping by code)
public SomeClassMap()
{
Map(x => x.User).Column("user_id").CustomType<UserType>();
}
public class UserType : IUserType
{
void NullSafeSet(...)
{
NHibernateUtil.Int32.NullSafeSet(cmd, ((User)value).Id, index);
}
void NullSafeGet(...)
{
int id = (int)NHibernateUtil.Int32.NullSafeGet(cmd, ((User)value).Id, index);
var userrepository = GetItFromSomeWhere();
return userrepository.FindById(id);
}
}

Automapper and NHibernate lazy loading

I am struggling with this issue:
I have a list of NHibernate objects called "Project". These objects contain a lazy - loaded list of "Branches". I am trying to pass a list of Projects to a WCF service so I am using AutoMapper to transform them to flat objects.
The problem is that even though the destination objects called "ProjectContract" does not contain a list of Branches, Automapper still invokes this collection and a lot of queries are made to the database because NHibernate fires the lazy - loading and loads the Branches collection for each project.
Here are the classes and the mapping:
public class Project
{
public virtual int ID
{
get;
set;
}
public virtual string Name { get; set; }
public virtual string Description { get; set; }
public virtual IList<Branch> Branches { get; set; }
}
[DataContract]
public class ProjectContract
{
[DataMember]
public virtual int ID
{
get;
set;
}
[DataMember]
public virtual string Name { get; set; }
[DataMember]
public virtual string Description { get; set; }
}
public class ProjectMappings : Profile
{
protected override void Configure()
{
Mapper.CreateMap<Project, ProjectContract>();
}
}
My question is: Is there a way to tell AutoMapper to not touch the "Branches" collection because I don't care about it and that is a proxy that will trigger many database calls?
I temporarily fixed this with MaxDepth(0), but there are other entities where I have collections that I want to transfer, and collections that I don't want to be touched, like this one. In that case, MaxDepth(0) will not work.
Thank you,
Cosmin
Yes, The AutoMapper Ignore function.
Mapper.CreateMap<Source, Destination>()
.ForMember(dest => dest.SomeValuefff, opt => opt.Ignore());

Why HashedSet forces loading lazy collection?

I query items with lazy collections in via nHibernate. Items are queried without fetching collections. But when i try to create HashedSet
var hashedSet = new HashedSet<Thing>(Session.Query<Thing>())
from those items all lazy stuff is fetched. Whats causing that?
[Serializable]
public class Thing {
public virtual String Name { get; set; }
public Thing() {
OtherThings = new HashedSet<OtherThing>();
}
public virtual ISet<OtherThing> OtherThings { get; set; }
}
Maybe you have overridden GetHashCode() in the entity (or any base class of it) and access the properties there?

Is the properties in Entity must be virtual when using FluentNhibernate?

Which entity FluentNHibernate uses as entity
I create some entity in Domain(or BLL), such as the following:
public class Role
{
public long ID { get; protected set; }
public string Name { get; set; }
public string Description { get; set; }
public List<User> Users { get; set; }
public Role()
{
Users = new List<User>();
}
}
And I want make use of FlunetNHibernate to map them, but get errors:
The following types may not be used as proxies:
Freeflying.Domain.Core.Profile: method get_ID should be 'public/protected virtual' or 'protected internal virtual'
Yes, I recall the programmer requirement when use FluentNHibernate, the entity should be like this:
public class Role
{
public virtual long ID { get; protected set; }
public virtual string Name { get; set; }
public virtual string Description { get; set; }
}
But It looks wired. Do you think so? How do you do when using FluentNHibernate? I don't want go back to Domain layer and add virtual for every property.
This is a basic requirement for using NHibernate; It allows NHibernate to generate a proxy class that descends from your class for lazy loading and such.
I have not seen a method of removing this requirement, though if such a thing is possible it would mean that you could not use lazy loading of objects and/or properties.
Here's a blog post that explains this a bit more; It also offers a way to avoid marking your properties as virtual, although I would really recommend that you do not use this method (marking classes to avoid lazy loading) as the benefits of lazy loading in most circumstances far outweigh the cost of making your properties virtual.

Nhibernate - Initialize lists - Best Practice?

I was just wondering about some CodeWarning (ConstructorsShouldNotCallBaseClassVirtualMethods), and if there is a better way to do it. I have a simple log collector class, and I am using NHibernate to retrieve some of the objects.
Some times I create objects by myself (of course) and add them to NHibernate for persistance. What is the best way to make sure that Lists are never NULL.
Currently I am doing this, but it does not seems "perfect". Any idea on this topic?
public class LogRun
{
public virtual int Id { get; private set; }
public virtual DateTime StartTime { get; set; }
public virtual DateTime EndTime { get; set; }
public virtual IList<Log> LogMessages { get; set; }
public virtual int LogMessageCount { get { return LogMessages.Count; } }
public LogRun()
{
LogMessages = new List<Log>();
}
}
Is LogMessages a persisted thing? If so, it's best practice to never expose a public setter. NHibernate gets weird if you retreive from the database and then replace that IList with a new one:
var myLog = session.Get<LogRun>(1);
Assert.True(myLog.LogMessages.Count > 0);
myLog.LogMessages = new List<Log>();
If you note, NHibernate is returning a proxied object and replacing it with a generic list will cause it to go wonky when you try and save back.
As a rule, I prefer to have a private field that I initialize and then expose only a getter to the client:
public class LogRun
{
private IList<Log> logMessages = new List<Log>();
public virtual int Id { get; private set; }
public virtual DateTime StartTime { get; set; }
public virtual DateTime EndTime { get; set; }
public virtual IList<Log> LogMessages { get { return logMessages; } }
public virtual int LogMessageCount { get { return LogMessages.Count; } }
public void AddLogMessage(Log log)
{
logMessages.Add(log);
}
}
Actually, I go a step further, the client gets an IEnumerable<> and I add a helper function for the add.
My implmentation would look like
public class LogRun
{
private IList<Log> logMessages = new List<Log>();
public virtual int Id { get; private set; }
public virtual DateTime StartTime { get; set; }
public virtual DateTime EndTime { get; set; }
public virtual IEnumerable<Log> LogMessages { get { return logMessages; } }
public virtual int LogMessageCount { get { return LogMessages.Count(); } }
public void AddLogMessage(Log log)
{
logMessages.Add(log);
}
}
I do the same thing, but I also wonder how big the perfomance impact is, since NHibernate will also create a new List<> for every default constructor call..
I think we're in luck though, and that it will work. Consider NHibernate creating a lazy-loaded list of LogRun's (which is why we mark everything as virtual anyway):
NHibernate will reflect over LogRun and create a derived class
NHibernate will make a proxy-list of the LogRun-derived class
--
When you load that proxy, it will instantiate some of those derived classes, however, the base-constructor is called first - creating the new list<> - then the derived constructor is called, creating a proxy-list instead.
Effectively, we have created a list that we will never use.
Consider the alternatives though:
Make the constructor protected, so that no one will call it, and make an alternative. For example, a static LogRun.GetNew(); method.
Allow public set-access to the IList<> and create it yourself whenever you create a new object.
Honestly, I think both are very messy, and since I'm (pretty) sure that the perfomance overhead on creating a new empty list on each constructor-call is limited, that's what I'm personally sticking too so far.. Well, at least untill my profiler tells me otherwise :P