I need to perform edits on my saga documents outside of the saga. I am trying to do the simple property update which is:
SaleSaga saga = session.Load<SaleSaga>(id);
saga.SaleSagaTaskId = taskId;
session.SaveChanges();
This does not work, I end up with this issue.
{"Entity Messages.SaleSaga had document key 'salesaga/d6b639c4-78a1-4be6-8e44-a283010b11a9'
but now has document key property 'salesagas/d6b639c4-78a1-4be6-8e44-a283010b11a9'
.\r\nYou cannot change the document key property of a entity loaded into the session"}
I am not sure why it is adding an 's' on to the end of "salesagas". I'm at a loss as to the best way to resolve this, any help would be greatly appreciated.
EDIT: This is for an NServiceBus saga and the error is occurring when attempting to save the edited document back to RavenDB.
The NServiceBus Saga Persister uses different conventions for storing sagas than the Raven default conventions. The Raven default convention is to take the class name and pluralize it. Apparently NServiceBus does not do so. So you have a mismatch by accessing the data in fundamentally different ways.
You may want to reuse the NServiceBus Saga Persister class. The Saga persistence code can be found here:
https://github.com/Particular/NServiceBus/tree/4.2.0/src/NServiceBus.Core/Persistence/Raven
How was the original object written? It looks to me like the reader and writer of this data might be two different systems, or two different versions of this system, and the the document conventions have changed.
Either use the original convention, or use a string identifier instead of a Guid.
Related
I'm having some message design head-aches. I want to start up an NServiceBus saga for a long running process. Part of the data needed to do the initialization is a list of constraints, which are implementations of an abstract base class. As I've understood the design philosophy, messages should ideally be
Self-contained, that is contain all the data needed to process them. Following this, I would pass along all the list of constraints in the message.
Versionable. NServiceBus does this by using an XML serializer which does not pass along type information (see this thread answer by Udi). In my case, that means I cannot on the recieving end pick up the specifics of the constraints.
The serialization problems can be "solved" by using the BinarySerializer, but this does not seem to be a recommended practice since it breaks versioning. The alternative is to send along some identifier so that the constraints can be retrieved from some datastore, but that would remove the "self-containedness".
Is there a third way here, or do I simply have to choose some "least bad" solution?
There is also the option of having these objects injected into your saga via DI.
Just create a boostrapping class that at startup will call:
Configure.Instance.Configurer.ConfigureProperty<yourSaga>(s => s.SomeProperty = value);
In my app, I have this scenario where I need to post an object to remoter server and get an object key back and then store the object locally. I have Core data and Restkit implemented in my app.
The object value are collected from user input. I couldn't figure out a great way to prepare the object before posting it to remote server. This object is an entity of type NSManagedObject, and I don't want to store it before I get the object id from server.
I came across this which suggested to use a transient object to handle this situation. But as discussed in that thread, this causes issue with code maintenance.
Is there a better way to handle this scenario? Thanks.
Make your core data model class adhere to the RKRequestSerializable protocol.
Then when the user input is validated, create an entity as normal and set it as the params value to the RKRequest, this will send your object as the HTTP body. Look inside RKParams.m for an example.
Also set the newly created entity as the targetObject for the RKObjectLoader. That way, when your web service returns the information (like the new unique ID), it will target the new object and save the new unique ID to this object without creating a duplicate.
Clear as mud?
PS: Oh and be careful mixing autogenerated core data classes with custom code! I recommend mogen to help you not lose code each time you make a change.
I have an exception occurring when saving changes to a self tracking entity:
AcceptChanges cannot continue because the object's key values conflict with another object in the ObjectStateManager. Make sure that the key values are unique before calling AcceptChanges.
I believe the problem is addressed in other questions such as: Self Tracking Entities - AcceptChanges cannot continue because the object's key values conflict with another object in the ObjectStateManager
My question is what is the best way to debug this problem both in development and production. Is there any further information that can be caught/accessed which will detail which entities or the entity types which are causing the exception.
If not will I have to write something to traverse the object graph looking for duplicate keys referencing different objects? If so does anyone have experience of this?
Further info:
My scenario involves the following - the client retrieves an entity via a WCF service which contains collections of further entities all with various FKs to other entities. These FK relationships are all included in the linq query so we have a complete object graph.
The views in the client use previously fetched entities for static data such as lookup tables for performance. If we have say a Customer object with a FK to User this will be loaded when retrieved from the service. If we now add another entity to the object graph e.g. Order and set a User property on this object which has the same Id as in the Customer object but the entity was retrieved at a different point and therefore using a different ObjectContext (i.e. the objects have the same Id but are not the same instance of the object) I get this error.
The link to the other question demonstrates ways to avoid this but I am looking to find more information about which entities are causing the problem so I can track down the error.
This usually happens if you try to AcceptChanges on the context which was used to load entities before - use new empty context for accepting changes. AcceptChanges cannot be used when any entity from STE is already loaded in the context - that is limitation of current STE implementation (but it can probably be removed if you rewrite the template).
As I know there are no detailed exceptions for this kind of problems. For debugging STEs check their generated code. You have whole STE code available so you can browse change tracker and search for entities but it will not be easy.
I'm actually not sure if it is even possible to define duplicates on the client but let's suppose that it is. If you have the control over client code the best way is diagnose the client code. Add some logging and find the reason for duplications. Then remove the duplication because fixing the issue on the client will be easier then fixing the issue on the service. If you don't have control over the client I would say that it is a problem of incorrect data passed to your client and let client's developers to fix it.
I had been banging my head against this problem for more hours than I cared to admit. Finally found that the cause of the problem was that I had listened to the ReSharper hint to make my
context provider static. since that occurred with a variety of other changes, I didn't think to check it as being the culprit. But in my case, that was the issue.
A couple of times on this current project developers have hit the same problem:
An object with related entities, i.e. an Order with a related Customer is sent back via WCF to entitywork to be saved. If the object is new we use AddObject() to put it back in the context and if it has changed, then we use ApplyCurrentValues() to update the object.
The Order object has changed, but the Customer object has not (unless the streaming via WCF affects it in some way). However, when calling SaveChanges() on the context the main object, Order in this example, is saved, but a new copy of Customer is also added to the database.
The workaround that we have found is to set the reference to Customer on Order to null before calling SaveChanges(), however this feels like a bit of a kludge.
What I'm looking for is the "correct" way to solve this problem, something akin to LazySaving = false, i.e. only save the object changed and don't try to create all the related objects.
Thanks in advance for any pointers.
I am not sure about Entity Framework, but I ran into this issue recently with NHibernate. I solved it by implementing save as follows
(1) Retrieve original entity from DB
(2) Update original entity from WCF Data Transfer object using AutoMapper
(3) Save original entity
I am not sure if you are trying to use your entities as DataContracts, in my experience its always better to use Data Transfer Objects rather than entities as you DataContract. If you dont, you continually run into all kinds of trouble, and DTO+AutoMapper gives you the control to solve most issues that you run into
http://automapper.codeplex.com/
I'm using NHibernate as my ORM. I have a situation where I have some stuff wrapped in an ITransaction. I am listening to the SaveUpdate event in NHibernate and then doing my entity validation in that SaveUpdate handler.
For one of my entities, I want to validate that the value of a certain property hasn't changed. So I figured that I would load up the value of the existing object from the database and compare it with the new value. The problem is that I called ITransaction.Commit() to save my entity object and the transaction hasn't actually been committed at the time that validation occurs, so I can't load the existing object from the database because the transaction has it locked.
So I guess I have a few different questions here:
- Is the SaveUpdate event the correct place to do validation?
- Is there another way I can do this so that I can do the validation that I need to do (getting the existing value from the database and comparing)?
I'm sure someone else out there has run into a similar situation...... hopefully!
If you want to see an example of how to do validation, I suggest checking out ScottGu's NerdDinner. Although he's using Linq to SQL for his ORM, it's very easy to adapt it to NHibernate.
I recently used a validation system similar to the NerdDinner one in an ASP.NET MVC + NHibernate project with great success.
Validation has nothing to do with persistence, so saveupdate is not the right place. The correct place of validation depends on: what you want to validate, your programming style, the UI framework you use to show the validation messages, etc. Personally, I prefer to put the validation on the place where things are changed, so I would put it in the change method that sets the property. I don't understand why you want to load the entity in the previous state, because that state is already loaded when you load it for the first time.