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?
Related
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
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());
Currently in my entities I'm exposing my collections as an IList but I've been thinking about exposing them as a IEnumerable to prevent users from manually adding to the collections. I have specific adds for these operations so that I can make sure my bi-directional relationships stay intact. A couple questions come to mind in this scenario.
If I expose them as IEnumberable does this mean I'll need an Add and Remove method for every collection that represents a relationship in my entities?
Is there an easier way to do this? I'm not against doing it this way just wondering.
Are you doing it this way?
Example:
public class OrderHeader
{
public virtual Guid OrderId { get; private set; }
public virtual IList<OrderLine> OrderLines { get; set; }
public virtual void AddLine(OrderLine orderLine)
{
orderLine.Order = this;
OrderLines.Add(orderLine);
}
//No need for a remove method since we expose collection as IList
}
Converting the class above so that we only expose IEnumerable would result in:
public class OrderHeader
{
public virtual Guid OrderId { get; private set; }
private IList<OrderLine> orderLines { get; set; }
public IEnumerable<OrderLine> OrderLines { get { return orderLines; } }
public virtual void AddLine(OrderLine orderLine)
{
orderLine.Order = this;
orderLines.Add(orderLine);
}
public virtual void RemoveLine(OrderLine orderLine)
{
orderLines.Remove(orderLine);
}
}
Yes, if you expose an IEnumerable it is best to add methods on the class to handle Add/Remove
A private backing field is a pretty good solution.
Yes, but keep in mind if you want truly read only access to the exposed collection use ReadOnlyCollection - http://msdn.microsoft.com/en-us/library/ms132474.aspx
Agreed with Dan's answer, with a minor change:
public IEnumerable<OrderLine> OrderLines
{ get { return orderLines.Select(x => x; } }
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.
I have problem with making mapping of classes with propert of type Dictionary and value in it of type Dictionary too, like this:
public class Class1
{
public virtual int Id { get; set; }
public virtual IDictionary<DayOfWeek, IDictionary<int, decimal>> Class1Dictionary { get; set; }
}
My mapping looks like this:
Id(i => i.Id);
HasMany(m => m.Class1Dictionary);
This doesn't work. The important thing I want have everything in one table not in two. WHet I had maked class from this second IDictionary I heve bigger problem. But first I can try like it is now.
It's not currently possible to use nested collections of any type in NHibernate.
Instead, you should define your property as follows:
public virtual IDictionary<DayOfWeek, Class2> Class1Dictionary { get; set; }
And add a new class:
public class Class2
{
public virtual decimal this[int key]
{
get { return Class2Dictionary[key]; }
set { Class2Dictionary[key] = value; }
}
public virtual IDictionary<int, decimal> Class2Dictionary { get; set; }
}
This way, you can map both classes and dictionaries normally, and still access your dictionary as:
class1Instance.Class1Dictionary[DayOfWeek.Sunday][1] = 9.4