开发者

Self Tracking Entities (STE)'s and partial updates with EF4 and mVC2

开发者 https://www.devze.com 2022-12-17 15:37 出处:网络
I have an MVC2 app where I am starting to use the STE\'s.I am looking for some clarification on how updates should work.

I have an MVC2 app where I am starting to use the STE's. I am looking for some clarification on how updates should work.

Background:

If I have a Blog entity with related category entities and Related post/comment entities. In MVC I am rendering a view with the main Blog entity and the categories but not the related posts. When I post back the Blog entity to the server I can see the related categories but not the posts (since they were not in the view) in the entity being serialized back to the server. Also, the Blog entity has a change state of 'Added'.

I then try to call Applychanges() and SaveChanges() on this Blog entity to the perform an update and it fails because of the FK relationship with posts and the fact that there are related posts in th开发者_如何学Ce database but not attached to the entity I am sending back.

With some further testing...If I grab a current instance of the Blog entity (with all the related FK entities) while connected to the server (state=unchanged), modify a property (state=Modified) and update it works as expected.

So my questions: If I have related entities that are not being rendered in a view and therefore not post back with the Blog entity should the update work?

Why does the Blog entity get post back with an 'Added' status and not 'Modified'? I would assume it would come back with a 'Modified' changedstate for all changed entities and then when I called ApplyChanges/SaveChanges() only the modified items would attempt to update and this is why I would not need all related entities.

Should I be able to pass an entity directly from the client and ApplyChanges()/SaveChanges() or should I be posting back to the server the entity, grabbing an existing copy from the database, applying changes to that copy and then posting the existing object back?


As to your first problem:

I then try to call Applychanges() and SaveChanges() on this Blog entity to the perform an update and it fails because of the FK relationship with posts and the fact that there are related posts in the database but not attached to the entity I am sending back.

This could possibly be caused by your second issue ("Added" state instead of "Modified"). The Context may be trying to add the Blog instead of trying to save the changes, hence a FK constraint error.

As for your second question:

Why does the Blog entity get post back with an 'Added' status and not 'Modified'? I would assume it would come back with a 'Modified' changedstate for all changed entities and then when I called ApplyChanges/SaveChanges() only the modified items would attempt to update and this is why I would not need all related entities.

The issue to consider is "are you using the same type generated code on server and client"? STE have been known to not keep track of changes when you use data-service metadata generated types. For STE, there is an important piece of code that gets activated in the constructor that does not persist through the metadata generated types and hence is th cause of this problem.

And as for your last quesiton:

Should I be able to pass an entity directly from the client and ApplyChanges()/SaveChanges() or should I be posting back to the server the entity, grabbing an existing copy from the database, applying changes to that copy and then posting the existing object back?

Yes, it is possible (I have tested this) to ApplyChanges()/SaveChanges() to entities coming directly from the client, regardless of where the entity originally came from (from the server to be modified or created on the client as a new entity to be added).


My observation with this was that, while STE's in EF4 work well in situations where the client is stateful, they don't work as expected in a stateless environment.

MVC highlights this shortcoming. For example, lets take a typical entity "User" and a typical scenario, the EditController and the Edit view.

When we go to our database (get user, start tracking, return) or our service (change tracking automatically turns on after deserialization), the entity behaves as expected within the controller and the view.

However, when the Post comes back, the entity that our Controller method gets is a new entity and not the one that was given to us on the Get request. So this entity has no change tracking, is in the Added state, and will blow our database up if we treat it as the same instance that was handed to us on the Get phase.

Currently, you can mark the EF4 STE as modified, apply changes and save when the entity is truly new or just marked incorrectly as Added. That's about all you can do right now to support this scenario. Unless the MVC team comes up with a better pattern to support STEs or unless you change the default behavior of the model binder when instantiating the model to cache the entity instance...


We struggled with very similar issues--surrounding updates. Based on the information out there we gathered that STE is not ready for production, but did consider using them.

Anyway, the issues here center around the distinction between attached and detached, and the interaction between the ObjectStateManager and the STEs.. in the example you describe that does work, it works because it's attached the whole time, and the STE never actually transitions to using its STE behavior (this only happens after being deserialized to the client, or they get re-attached to an attached entity).

In answer to why they show up as added:

For instance, when STEs are instantiated, change tracking is deactivated and the default state in the change tracker is Added.

I find this all confusing, and interviews with Julia Lerman, and posts online, seem to indicate that the current STE release isn't ready for the real world...

See this response from Diego Vega (EF Team)

When you use STEs in this mode, they behave roughly as plain POCO objects. For example, you can manipulate the graph directly or use the APIs in the ObjectContext and ObjectStateManager, and you have to call DetectChanges to make sure that the state manager is in sync with the graph at any point before calling SaveChanges.

Most importantly, the standard Object Services API is not aware of STEs and so, such methods as AcceptAllChanges (which is the one that in your example is called implicitly during SaveChanges and resets the ObjectStateManager state for the complaint object to Unchanged) have absolutely no impact on the state stored by the STEs.

http://social.msdn.microsoft.com/Forums/en/adonetefx/thread/557e6db0-51df-45e5-a2e9-c31995969554

Hope this helps


I don't believe I have ever said STEs are not ready for the real world. They just won't be for everyone. They are a pretty good tool for the dataset/datatable users who just want something that will work as easily. For these users (and there are a lot of them out there) putting the STE entities in the client app is not an evil thing. THey probably already own both sides of the pipe.

0

精彩评论

暂无评论...
验证码 换一张
取 消