the nhibernate cross machine lazy load problem - c#

i got a client a server and a db
db mapped to server with fluent nhibernate.
so far so good
the client talks with the server with wcf.
i want to implement lazy loading on client side.
is there any solution out there?

AFAIK there is no solution for that, lazy loading works with nhibernate's proxy mechanism which is very intrinsic to its implementation.
there was one project called Nhibernate.Remote but this has been abandoned.
nhibernate would work over wcf, but without lazy loading.

The nature of WCF would be to learn towards your data being shaped prior to sending, ie., it's already been retreived and put into a datacontract of some sort.
Possibly you could provide a parameter on the inital service call to indicate whether child properties should be populated, although how far you go is always going to be tricky.

when i realized that it can't happen, i decided to work with the projection and the result transformer.
it works good.
if i need to load some lazy loading collection i just iterate it on server and send it back to client,
when i wanna update a partially selected object i have to reselect him from db and update the full data entity.
but it's worth it

I'm sorry to be pessimistic but making NHibernate work with lazy loading over WCF is NOT GOING TO WORK.

With the below code WCF can work with lazy loading:
var proxy = myObj as INHibernateProxy;
myObj = (myObj)proxy.HibernateLazyInitializer.GetImplementation();

Related

Entity Framework - Efficient eager loading with long chains of dependent objects?

I have an issue, which I assume many professional developers will run into. My workplace has adopted entity framework. We use it, and love it. However, we seem to have run into a very frustrating limitation.
Let's assume you have an object chain as such
A -> B -> C -> D
We are professionals, so these objects have a lot of data, and there is a lot of them in their respective database tables. It seems EF has a terrible time loading anything past object B. The SQL queries it generates are really inefficient and not good. The call would be something like
context.objects.include("bObjectName.cObjectName.dObjectName").FirstOrDefault(x => x.PK == somePK);
We have gotten around this by explicitly loading objects past that second level with the .Load() command. This works well for single objects. However, when we talk about a collection of objects, we start to run into issues with .Load().
Firstly, there does not seems to be a way to keep proxy tracking of objects in a collection without the virtual keyword. This makes sense because it needs to overwrite the get and set functions. However, this enables lazy loading, and .Load() doesn't map entities when lazy loading is enabled. I find this to be somewhat odd myself. If you remove the virtual keyword, .Load() does automatically link loaded objects to the relevant objects in context.
So here is the crux of my issue. I want proxy tracking, but also want .Load() to map the navigation properties for me. None of this would be an issue if EF could generate good queries. I understand why it can't, it has to be a one show fits all kind of thing.
So to load the third tier of objects I might create a loader function in my service layer that takes all the primary keys of the second tier of objects, and then calls a .Load() on them.
Does anyone have a solution for this? It seems like EF7, or Core 1.0 solves this by:
Removing lazy loading entirely, which we could shut off as well, but it would break a lot of older code.
Adding a new "ThenInclude" feature, which supposedly increases the efficiency of chaining includes massively.
If turning off lazy loading is the answer, that's fine, I just want to exhaust all options before I waste a lot of time redeveloping a huge webapps worth of service calls.
Does anyone have any ideas? I'm willing to give anything a shot. We are using EF6.
EDIT: It seems the answer is to shut off lazy loading at a context level, or upgrade to EF7. I'll change this if anyone else manages to find a solution whereby you can have proxy tracking with forced eager loading on a single object for EF6.
You're absolutely right about chained .Include() statements, the performance documentation warns against chaining more than 3 as each .Include() adds an outer join or union. I didn't know about ThenInclude but it sounds like a gamechanger!
If you keep your virtual navigation properties but turn off Lazy Loading on the DbContext
context.ObjectContext().ContextOptions.LazyLoadingEnabled = false;
then (as long as Change Tracking is enabled) you can do the following:
var a = context.aObjectNames.First(x=> x.id == whatever);
context.bObjectNames.Where(x=> x.aId == a.Id).Load()
This should populate a.bObjects

WCF, SOAP, EF, POCO

We are developing a application which should use Entity Framework and its an simple WCf Soap service (not Wcf data service). I am very confused now I have read these following posts but I don't understand where to go This question is almost the same but I have a restriction to use POCOs and try to avoid DTOs. Its not that big service. But the link which I mentioned ,in answer its written that if I try to send POCO classes on wire, there will be problem with serialization.
This post has implemented the solution which related to my problem but he did not mention anything related to serialization problem. He just changed the ProxyCreationEnabled =false which I found in many other articles as well.
But these posts are also little old, so what is the recommendation today. I have to post and get lot of Word/Excel/PDFs/Text files as well, so will it be OK to send POCO classes or it will be problem in serialization.
Thanks!
I definitely do not agree with this answer. The answer mentioned suggests to reinvent the wheel (The answer does not even indicate why not using POCOs).
You can definitely go with POCOs, I see no reason to have serialization issues; but if you have any, you can write DTOs for these specific problematic parts and map them to POCOs in the Business layer.
It is a good practice to use POCOs as the name itself suggests; Plain Old CLR objects. Writing the same classes again instead of generating them will not have any advantage. You can simply test it.
UPDATE:
Lazy Loading: Lazy loading means fetching related objects from database whenever they are accessed. If you have already serialized and deserialized an entity (ex. you have sent the entity to client side over a wire), Lazy Loading will not work, since you will not have a proxy in the client side.
Proxy: Proxy class simply enables to communicate with DB (a very simple definition by the way). It is not possible to use an instance of Proxy in the client side; it does not make sense. Just seperate the Proxy class and POCO entities into two different DLLs and share only the POCO objects with the client. And use the proxy in the service side.

Intercepting NHibernate Lazy-Load behaviour to return null if not connected to a session?

This seems like it should be an obvious thing but I've been searching for the answer for hours now with no success.
I'm using NHibernate to persist a domain model, with a service layer that serves an ASP.NET MVC front end (the 'service layer' is currently just a standard class library but may be converted to WCF in the future). The web app asks for the data it wants and specifies the collections on the domain object that it needs, the service layer takes the request, loads the object and required collections (using lazy loading) and passes the object back where it is transformed using AutoMapper to a viewmodel friendly representation.
What I want to be able to do is load the required collections, detach the object from the session and pass it to the front end. However, when AutoMapper tries to map the object this causes a an exception because it's trying to access collections that haven't been initialized and the session is no longer available. I can leave the object connected but in this case the AutoMapper transformation ends up causing all the properties on the object to be lazy-loaded anyway and this won't be an option is we go down the WCF route.
What I want to do is alter this behaviour so that instead of throwing an exception, the collection returns null (or better yet empty) when it is not connected to a session. This was the default behaviour in Entity Framework V1 (which admittedly didn't do auto lazy loading), which I worked with previously but I can't find a way to do it in NH.
Any ideas? Am I on the wrong track here?
EDIT- To be a bit clearer on what I'm trying to achieve, when accessing a collection property I want this behaviour:
Connected to session: lazy-load collection as normal.
No session: property is null (rather than throw exception)
UPDATE - Following this post by Billy McCafferty, I've managed to implement a solution using IUserCollectionType that seems to work so far. Rather than use the provided PersistentGenericBag as he does though, I had to create new types that changed the behaviour when not connected to the session. It's not perfect and requires some very ugly mappings but at least I don't need to touch my domain objects or client mappings to get it working.
The most appropriate solution in this case is probably to check in AutoMapper for lazy-loadable fields if they were indeed loaded with NHibernateUtil.IsInitialized(). Not sure how/if possible to make Automapper use this check for all implicit property mappings though.
Old question but this is what we did to solve the same issue, hopefully it helps to set you on correct path if somebody stumbles upon this problem.

nhibernate can you lazyload without proxies?

I've started digging into Nhibernate and although there are many things I do like, there is one ting I dislike: the "generate proxy"/lazy load mechanism. The idea that I have to maintain some sort of reference to the ISession and make sure the entities are associated with the session before accessing a property that might trigger lazy-loading is a bit more plumbing in my viewmodels than I appreciate. In the last ORM mapper I used, we had a different approach to lazy loading which enabled used to disregard the session problem entirely at the cost of less POCO entities. I basically want to do the same thing with nhibernate, with some syntax similar to this:
public class Order
{
// this will introduced through the ctor using for ex an interceptor and Castle Windsor
private IOrmService ormService;
List<OrderLine> details = new List<OrderLine>();
public IEnumerable<OrderLine> Details
{
get
{
ormService.LazyLoad(this, o => o.Details);
return this.details;
}
}
}
Where the idea is that the ormService will simply disregard the lazy load request from the entity if the collection has already been loaded (nevermind the state management issue :-)). I looked into the NHibernateUtils-class, which has some Initialized and Initialize-collection methods, but they assume that you are using proxies. Basically, i need a way of telling nhibernate someting like: "hey, populate this property using this session which i'm giving you". The state-management, etc can be handled externally. Is there support for doing this in Nhibernate?
I'm a bit confused with your problem. I feel like following Hibernate best practices should be enough, no need to re-invent what already there. Here are a few comments.
The idea that I have to maintain some
sort of reference to the ISession and
make sure the entities are associated
with the session before accessing a
property that might trigger
lazy-loading is a bit more plumbing in
my viewmodels than I appreciate
If you follow the open session in view pattern, this becomes really easy.
Where the idea is that the ormService
will simply disregard the lazy load
request from the entity if the
collection has already been loaded
That's what the lazy proxy does already.
Basically, i need a way of telling
nhibernate someting like: "hey,
populate this property using this
session which i'm giving you".
That what you do when you detach/attach objects to a session. The lazy items will be loaded according to the session the object is attached to.
The answer is no you cannot have lazy loading without proxies. Either the proxies need to be created by NHibernate or any type of class or pattern you implement will produce the same end result except you'll just have moved around where/how the proxies are generated.
For the lazy loading to work, it inherently needs the ISession otherwise there would be no way for it to connect to the database to retrieve the needed values.
The way NH has implemented its proxies pattern is probably the best you will ever achieve atleast until .NET 4.0 the new dynamic word might shake things up a bit.

DTOs vs Serializing Persisted Entities

I'm curious to know what the community feels on this subject. I've recently come into the question with a NHibernate/WCF scenario(entities persisted at the service layer) and realized I may be going the wrong direction here.
My question is plainly, when using a persistent object graph(NHibernate, LINQ to SQL, etc) behind a web service(WCF in this scenario), do you prefer to send those entities over the wire? Or would you create a set of lighter DTO's(sans cyclic references) across?
DTOs. Use AutoMapper for object-to-object mapping
I've been in this scenario multiple times before and can speak from experience on both sides. Originally I was just serializing my entities and sending them as is. This worked fine from a functional standpoint but the more I looked into it the more I realized that I was sending more data than I needed to and I was losing the ability to vary the implementation on either side. In subsequent service applications I've taken to created DTOs whose only purpose is to get data to and from the web service.
Outside of any interop, having to think about all the fields that are being sent over the wire is very helpful (to me) to make sure I'm not sending data that isn't needed or worse, should not get down to the client.
As others have mentioned, AutoMapper is a great tool for entity to DTO mapping.
I've almost always created dtos to transfer over the wire and use richter entities on my server and client. On the client they'll have some common presentation logic while on the server they'll have business logic. Mapping between the dtos and the entities can be dumb but it needs to happen. Tools like AutoMapper help you.
If you're asking do I send serialized entities from a web service to the outside world? then the answer is definitely no, you're going to get minimal interoperability if you do that. DTOs help solve this problem by defining a set of 'objects' that can be instantiated in any language whether you're using C#, Java, Javascript or anything else.
I've always had problems sending nHibernate objects over the wire. Particularly if your using a ActiveRecord model. and/or if your object has ties to the session (yuck). Another nasty result is that nHibernate may try and load the object at the entry of the method (before you can get to it) which can also possibly cause problems.
So...getting the message here? problems, problems problems...DTO's all the way

Categories

Resources