Nhibernate: update POCO, persist, collect children? - c#

I still have difficulties with some NHibernate terms so please bear with me.
I am building a POCO class based off a web submission. The web user will be changing some scalar properties. The POCO will already be persisted in the database. I want to save changes to the POCO to the database, collect the child objects (which should be unchanged) and return the POCO's graph so I can send feedback back to the user.
What is the proper way to do this? Is this "detached"? What is the appropriate method for connecting the child collection? Can it be done in one database batch?

Persisting changes to your object is easily done using Session.Update().
retrieving child collection is done either implicitly (by accessing the collection property which causes nHibernate to fetch it from the DB), or explicitly, using the Fetch() method.
For example- var users = QueryOver<User>().Where(u => u.Age > 18).Fetch(u => u.Children).Eager.
In general, for a web app, I would recommend reading a little about the 'session per request' pattern. (this example is a little bit of an overkill for my taste, but it explains the concept quite well).
Also don't forget to always use transactions.

Related

Breeze Custom Actions

I've been using BreezeJS in a number of projects for a while now, and I have to say that in most ways, it makes your life MUCH easier, which is why I keep coming back to it. However, I seem to consistently run into a scenario where it falls completely flat, and I cant seem to find any "correct" way of working around this issue.
Let me explain. One of the best things about BreezeJS is that it follow this UoW pattern that allows you to save entities using the saveChanges method of the entity manager, like EF.
However this is also a part of the problem, because as you develop more and more sophisticated application, I sometimes feel this approach is not always appropriate. I find that often I have:
Operations that doesn't really involve creating entities on the client, but rather involve executing an action on the web api that may result in the creation of various entities or other forms of state on the server, that should then be send back to the client.
Operations that involve entities with properties, that cannot be saved because some of them are private to the server, and should not be put on the client (often solved with a JsonIgnore for the client, but comes with issues when you start persisting the given entity again)
I feel that there is one thing that could solve these issues relatively easily, and it is a concept that already exists in OData: Actions. Actions that can be performed globally, on entity sets or on specific entities and then return either custom objects or entities that will be directly tracked by BreezeJS.
Currently, I find myself doing the following workaround (which I don't know if is appropriate):
Make a "Resource" action on the BreezeController that represents an action rather than an an actual resource. This takes in a custom parameter object and returns a non-entity object, that may contain actual entities (as described under "Cool Breezes" with the Lookups, because these will then be track by BreezeJS)
Use the "ajaxpost" breeze lab to allow querying a resource with a POST instead of a GET so any sort of arguments can be passed in.
Is there a more appropriate way of accomplishing something like this? Are there future plans to support custom actions?
An approach I have seen to solve this type of operation, is to simply make these sort of operations "around" the breeze api controller. That is, simply using an ApiController that has nothing to do with breeze. But I kinda feel this defeats the purpose of breeze, because then, if the operation results in the creation or deletion of entities, you must start tracking them by yourself on the client, by either creating them locally, or by issuing another breeze query to go get them. This really gets tiresome if you need a lot of these types of operations.
I’m struggling with the same issue myself. I have an app that uses breeze to store trades in a SQL database and after the trade is stored, another user can use the app to send the trade to a backend trading system. I created an OData action to do the import to the external trading system so I can do a post to /trades(123)/ImportTrade. When I get the metadata for the service using /$metadata it sees that the trades entity has this action (it's in the metadata).
I was hoping that breeze would see this in the metadata and create a method on the trades entity to do a post to my OData action, but it does not. This would be a great feature if it was added to breeze (exposing OData actions as methods on entities).
As a workaround I have extended the breeze entity myself with a custom method that does the post to /trades(???)/ImportTrade.
It would be great if breeze could handle this for us!
Your approach using ajax post is a good way to do thouse kind of things...
You can also make your own context by inheriting from BreezeContext that has nothing to do with a DB, and do your actions there with out saving the entites and still get the result back as a non tracked object or entities.
If you create a new entity on the server (not always a good idea with breeze, but still can still be done) you have to make sure that breeze will still generate the temp keys for that entity.
You can use the temp key generator or just delete the primary keys of the non tracked object.
You can use the metadata of that entity type in order to get it's primary key properties and then delete them using javascript like so: delete obj[prop]
then use createEntity with the non tracked entity that doesn't have primary keys.
Breeze will then generate the primary keys for you and your all set.
I also hope that Breeze will address the need to do custom actions that may return a custom non tracked object in a more intuitive way
Hope this helps

How to detect the changed poco entities in an ObservableCollection over wcf in N-Tier architecture?

I have following layers in my applicaiton
Date Layer (reference to Model)
Business Layer(reference to Model ,Data)
Model
Service(WCF)-(reference to Model,Business Layer)
UI (WPF/Silver Light) - Connected via WCF service
How do i detect the changed poco entities in an ObservableCollection in UI layer?
for sending it back to server from client side for saving ? instead of sending all data back to sever side(via WCF)?
or
how to perform add/delete/update operation on entities in the collection in UI layer?
I am using
VS2010/2012
C#
EF 5
ADO.NET POCOEntityGenerator With WCF Support(for generating .tt templates from Model.edmx)
SQL Server 2012
Even though searched a lot of places I didn't find a proper solution..
please help if any ideas...
Thanks...
The method i followed to create My application is given below link
http://www.toplinestrategies.com/dotneters/net/wcf-entity-framework-and-n-tier-solutions-part-2/?lang=en/comment-page-1/#comment-1954
Only proper solution is to do the change tracking manually. Each POCO object will have IsDirty property and each property of this object will have IsDirty = true in it's setter.
One way to make it less manual would be to create a framework, that will create wrapper classes, that will do this for you, but this requires large dose of reflection and code-generation. Also, it will still require all properties to be defined as virtual.
But generally, you want to refrain from making UI that would require this kind of tracking. When you want to change an entity, load only that entity in Edit window.
POCOs are well-suited for transmitting data between client and server. However, if you’re looking for objects to actually work with on client and/or server side you may want to consider using self-tracking entities (STE) as these entities contain logic to track their actual changes and status.
Yet a better solution is to use the N-Tier Entity Framework which provides functionality to work with EF in n-tier applications. See http://ntieref.codeplex.com/ for more details.
If you are using EF, then your entities have a 'HasChanges' flag you can test against before submitting changes to your context.
e.g.
if (this.CurrentEntity.HasChanges || CurrentEntity.EntityState == EntityState.New)
{
this.SubjectContext.SubmitChanges(Submit_Completed, saveDetails);
}

NHibernate calling "get" from a property twice

I have this situation: I'm developing a software with Spring.net and Fluent NHibernate, and I noticed something very unusual with NHibernate's behavior. I really don't know whether it's correct or not, but for my software it cannot happen. I noticed that NHibernate is calling twice all the getters, even when I'm updating something on the database. For exemple, when I try to insert some values on dabatase, NHibernate gets the value from the property to put on database, and then it triggers a new get again, which I don't know why and how is called. I think it tries to retrieve the value from cache to compare both values (database and cache) and save the updated value on cache.
By the way, for some entities I have a secondary cache level, but this situation happens with entities that have and don't have this secondaty cache level.
Any help? Thank you.
You should be able to find it out using print of current stack track
in particular getter and compare it to other traces. This should
show you starting point.
What get into my mind:
Backward get for caching because of second level cache as it stores properties of entities only.
What about has-code computing? Is it use properties to or fields?
Verification whether object in session is as same in the database.
If with get you mean NHibernate runs a select on the database to retrieve the object, within an insert/update this will be done only if you provide the ID of the object and the object is not already available within the session.
If you don't have the object in the database and want NHibernate to insert a new one, do not provide an ID and configure the generator of your ID map correctly
Otherwise make clever use of proxies and prevent NHibernate to retrieve the full object by using Load<T> which will not actually hit the database but puts a proxy into the current session scope.

Change tracking entities from multiple sources in Domain Driven Design

I am currently in the process of developing a a rather big web application and is using domain driven design.
I have currently run into some trouble with tracking changes to my Product entity. The thing is, products are constructed partly from data in SQL Azure, partly from data in Azure Table Storage. If certain properties are changed, I will need to persist to both, other changes only to one.
As a result I can not use NHibernate or Entity Framework for tracking changes. For instance the Price argument on the
public void AddPrice(Price price)
method on the Product entity must be persisted to SQL Azure, calculations on a range of prices will take place and the result will be saved to Azure Table Storage.
How would you solve this?
Thoughts:
1) I thought about implementing my own change tracker based on Castle.DynamicProxy, but that seems rather tedious.
2) Implement events internally in the domain entities. This is not a good thing.
Scattering one entity across several persistent stores might not be a good idea. To be more precise, it might mean that it's not one and the same entity and could be split up in smaller, more accurately designed parts instead.
calculations on a range of prices will take place
Are you sure these calculations affect the Product entity and should be handled by the same NHibernate/EF session used in the Product repository ? Since they have to be stored elsewhere, don't they make up a first class notion in the ubiquitous language, resulting in a separate entity with a persistence logic of its own ?
See http://ayende.com/blog/153699/ask-ayende-repository-for-abstracting-multiple-data-sources
What do ORMs do? They take a copy of the data that's used to restore your object into its current state, just before they hand you a reference to the object. When behavior has been applied to the object and you're asking to persist it, the ORM will compare its copy of the data to the data currently inside the object and flush changes accordingly. Why not do the same? The only difference is that not all detected changes will be flushed to the same datastore.
HTH.
BTW, any concurrency going on here?

Adding custom navigation properties using SPs in .NET Entity Framework 4

My company uses stored procs for all SELECT operations so it's making it rather difficult for me to create sensible navigation properties. I'm not too concerned at this point whether they're lazy loaded or not.
So for example I created an entity for Customer then created a FunctionImport to map GetAllCustomersSP to return a collection of Customer entities. But I want a navigation property "Orders" on each Customer entity.
But if I use the Customer entity partial class to just add this property, the problem is that I don't have access to the original Context, so I can't call the GetCustomerOrdersSP either explicitly or deferred.
The only option I can see is to modify my repository to add these properties in explicitly, which seems lame because it puts the entity logic into the repository.
Is there something I'm missing here? I can see in the entity model designer that I can specify custom insert, update, delete SPs but I don't see any way to use select SPs to actually retrieve the data.
I agree with Tim here...any solution you come up with isn't going to fully leverage the ORM and will be a potential nightmare to maintain. I would suggest creating a model, in code, that is framed in the manner in which you want to develop.
In the Data Access layer of your app, you can map your data objects that use SPs to hydrate your model objects (have a look at AutoMapper). Your app will only know about your model objects.
Doing this will give you a consistency in how you interact with the objects, and you can begin to apply pressure to the powers that be to allow more fine grained access to the tables, at which point, you can adjust your Data Access Layer to support EF and remove SPs. At this point you would be able to consider migrating the objects you created to POCO objects that are persisted via EF.
We had a similar issue in that granting raw DB access was "forbidden". We overcame this problem by using a model in which we only grant access to tables as they are used, not the entire database, and by ensuring the DBA that EF uses parameterized SQL, eliminating the concern of SQL Injection.

Categories