In my application I need to save with NHibernate entities received from WCF service.
Currently I'm using session SaveOrUpdate method for this purpose.
Often we don't need to edit reference properties, so from client I receive object, which has empty collections. But I don't want this empty collection to reflect in database.
Example:
public class Product
{
public virtual string Name {get;set;}
public virtual IList<Stores> Stores {get;set;} <--- Stores is empty, but should not be cleared in databse.
}
Thanks,
Oksana.
As far as I understand it, you want to update certain properties of the object if it already exsits, and no touch others, is that correct?
Well, basically, in such a case what you'd need to do is this:
establish an NHiberate session
based on some ID, load the current state of the object from the database
update those properties you want to update from the entity you've received in your service call
save the modified object back
With this approach, you'll only update those properties you want, and everything else is being left alone.
Does that seem like an approach you can work with?
Marc
I'm not sure to understand the question. If you are new to NHibernate have a look at the documentation with the term cascade. This defines what is persisted when an object containing others has to be saved.
Related
I'm new working with WCF and so far I understand the basic to create a web service with it, but I have a problem with some of my methods.
I have my services defined as follows link and my web.config is like this. My model has 5 entities, one of them is not related to the rest for the moment, the other four are related among them, my model looks like this. I have endpoints that do the usual CRUD operations, there's no problem inserting, updating or deleting, but when I tried to get the list of Eventos, Regiones, Clusters and Dispositivos, the method fail and doesn't return anything.
The funny part is that if I generate the database from my model again, restart the service and reinsert the data again, I can get the data from the endpoints with no problem. But if I stop the service and restart it againg, then it fails once again.
This only happens with the four entities that are related, all the endpoints for Usuarios work fine, but for the other 4, the endpoints fail only when I'm trying to retrieve all of the entries or just one entry of an entity. If I try to insert, update or delete an entry from any of these entities there's no problem, the problem is only present when I try to get the list of entries or just one entry.
For example if I try to access the url 127.0.0.1:81/SismosService.svc/region/index it returns in Google Chrome Error 324 (net::ERR_EMPTY_RESPONSE), but that doesn't happen with 127.0.0.1:81/SismosService.svc/usuario/index, that url return me the correct JSON object I'm expecting which looks like this:
{"Meta":{"Method":"GetUsuarios","Status":"ok"},"Response":[{"ApellidoM":"Mendoza","ApellidoP":"Arvizu","CreatedDateTime":"/Date(1357947261710-0600)/","Nombre":"Uriel","Password":"uriel88","UpdatedDateTime":"/Date(1357947261710-0600)/","UserName":"uriel88","UsuarioId":1},{"ApellidoM":"Mendoza2","ApellidoP":"Arvizu2","CreatedDateTime":"/Date(1357947273070-0600)/","Nombre":"Uriel2","Password":"auam","UpdatedDateTime":"/Date(1357947273070-0600)/","UserName":"auam","UsuarioId":2}]}
Why are these endpoints failing?
This was caused by trying to send objects with circular referencing, since EF creates the objects for a determined entity, if for example you want to send an object foo of type EntityA, which has a property of type EntityB, that property will have a property of type EntityA that references the original object foo, this creates a circular reference which can not be parsed into JSON by the service.
What I did was the following: To create a new instance of type EntityA and assign to each of its properties the values you're interested from the foo object, leaving the objects that creates a circular reference as null.
I have a service object that is responsible for some business logic validation. What it does, before issing Update to repository, is checking whether entity that it works on complies to some business rules.
One of that rules that is must check is if Status property of the entity didn't change when compared to entity that is in database. Because I use repositories that share the same ISession, when I try to get entity from database, in order to get an object for comparsion:
if (fromDbEntity.Status != entity.Status) throw new Exception("Cannot change status...");
I'll always get fromDbEntity that is in 1st level cache - so I work on the same object.
Is there a way to force NHibernate/Repository to get entity from database even though it's already in the scope of the session?
Evict entity from session before loading fromDbEntity
session.Evict(entity);
You can check the official documentation for more details: Managing the caches
The con about this is that you will need to manually call SaveOrUpdate for entity since now the object is out of the session.
You could, as Claudio suggests, evict the entity from the session, then load your fromDbEntity, do the comparison and then Merge the entity again with the session.
Other thing you might do is loading the fromDbEntity using the stateless session instead.
But is this really necessary? Couldn't you just make your Status property read-only? NHibernate is perfectly capable of using fields for accessing data. Or you could make your property setter protected:
public virtual Status Status { get; protected set; }
This way the user won't be able to change the property value, so there's no need to check whether current value is different from db one.
I had a similar issue, I solved it by clearing the session before any call that I want to go all the way to the data base.
session.Clear();
It's a little overkill but it works.
The way you sate your logic, it sounds like there's a potential bug. A much better solution would be to turn on dynamic-update, thus only updating changed values, then validate that no one has changed Status before saving.
I have a problem when sending Entity Framework-generated entities with navigation properties over WCF. I have a Securities database for storing financial data and two tables inside it:
Stock : Id, Symbol, CompanyName, ExchangeName
Option: Id, StockId, OptionType, Strike
I created an Entity Framework model for this database. Then I created WCF service which exposes generated Stock and Option EF entities to the clients.
My generated entity Stock has navigation property EntityCollection<Option> Options.
When trying to return Stock entity from WCF service to the client, I get an SerializationException: WCF cannot serialize Options navigation property because database connection has been already closed.
I can call Options.Load() method when database connection is opened to fill Options property, but what should I do if I don't want to load full object graph for Stock entity?
I've fought with this one for a while.
First, I turned lazy loading off. But I still had problems with cycles in my object graph.
Then, I put [DataContract(IsReference = true)] tags on all of my entities. That worked, but I still had a lot of performance issues do to a denormalized database.
Finally, I broke down and make dtos and I use AutoMapper to populate them.
One of my coworkers told me to do this from the beginning, and I should have just listened to him. Do yourself a favor and don't make the same mistake that I did.
Edit
I forgot to mention that I had issues deserializing entities that has properties of type ICollection<T>. These will deserialize as arrays. Somehow T[] implements ICollection<T> but Add and Remove will throw exceptions. This was another reason to use DTOs.
With EF5, not sure with EF4, this might work. Change the navigation property setter to private.
public class OptionEntity
{
// properties
// navigation
public virtual StockEntity Stock { get; private set; }
}
How can I make such behaviuor in NHibernate:
There is an entity called User in my domain
// I ommit mapping attributes
public class User
{
int Id {get; set;}
int pId {get; set;}
//....other props, such as Login, Name, email...
}
I need to make full copy of it, when updating. pId must be set to original Id. Old entity must be untouched.
So this must be like some versioning system, where pId - is immutable identity, and Id - is like version. I`ve tried to use Version mapping attribute, but it just updates Version field, withou recreating full entity. What approach will be better?
I wrote a versioning system for our application. I split the versioned object into two classes, one that represents the whole object and one for its versions.
In our software, the versioning is part of the business logic. The application provides access to the history and the user has some control over the versioning.
A new version is therefore created in memory. You need to perform a deep-copy. You could implement this by implementing an interface in the root entity and all its children. This interface provides a method DeepCopy which is recursively called through the object graph.
There is also a protected MemberwiseCopy method in object, which could be helpful. It does not a deep copy.
We didn't want the pain to maintain the code which copies each single property. So we are using serialization to copy an object graph in memory:
public static T CopyDataContract<T>(T obj)
{
NetDataContractSerializer serializer = new NetDataContractSerializer();
using (MemoryStream stream = new MemoryStream())
{
serializer.Serialize(stream, obj);
stream.Position = 0;
return (T)serializer.Deserialize(stream);
}
}
Additionally, we have methods in the entities which reset the ids and do some other cleanup. This is also done recursively though the object graph.
For now, it works fine. In the future we probably need to refactor it to the interface implementation, which is a bit cleaner.
Depending on whether history is NOT part of your domain logic I'd suggest using triggers. By not being part of domain logic I mean - you don't need to show it to users, you don't make copies out of historical version.
By using triggers you have several options - the simplest (and implying that you really need to save history only for handful of tables) - would be having a separate _history table that's a copy of your original table.
All in all it really depends on what exactly you are after.
I've got this Silverlight Prism application that is using MVVM. The model calls a WCF service and a list of data is returned.
The ViewModel is bound to the View, so the ViewModel should have a List property.
Were should I keep data returned by a WCF service in MVVM?
Should the List property be calling into the Model using its getter? Where the model has a ReturnListOfData() method that returns the data stored in the model.
Or does the ViewModel stores the data after the Model is done with calling the server?
This is a follow up on Where to put the calls to WCF or other webservices in MVVM?
Generally if I need to keep the Model objects around (I consider most things coming back from a WCF service a Model object) I will store it in my ViewModel in a "Model" property.
I've seen people go so far as to create a standard Model property on their base ViewModel type, like this (I don't do this, but it's nice):
public class ViewModel<ModelType> : INotifyPropertyChanged ...
{
//Model Property
public ModelType Model
{
...
}
}
It's really up to you. Keeping them as close to their related ViewModels is probably the thing to take away here.
It really depends on other aspects of your application. E.g. how's the data returned by ReturnListOfData() used? Are there other components interested in it? Does user update elements in the list? Can it create new elements that he'll want to save later? etc.
In the simplest case you'd just have a List property exposed by your viewmodel to view, and you'd reset that list to whatever ReturnListOfData() returned. It will probably work for a case when user simply performs a search, doesn't do anything to the data later on, and there's only one view that is interested in that data.
But suppose a user wants to be able to modify elements of that list. Clearly, you'll have to somehow track the changes in that original list, so then when user clicks save (or cancel), you'd send to the server only elements that were changed (or added) or restore the original elements if user clicks cancel. In this case you'd need a Model object, that would keep the original data, so then your viewmodel contains only its copy.