By Ben Hayat - 1/24/2007
I first summarize my question then follow it with more detail.
When SF is saving an updated record, does it write back every column of the record or only those columns that were affected.
User1 opens customers 1020 to update the email address of the customer. While she is on the phone with the customer [and has not pressed the save button yet], another process in the system [say invoicing] updates the customer balance. (Optimistic Concurrency).
User finishes with the customer and presses the save button:
a) Does SF write back ONLY Email column back without affecting the new balance?
b) Does SF write back the WHOLE record back and putting the old Balance to the database?
c) Or does SF raise an error that the record has been changed since it was originally read?
if C, then what action is left for the end user to take to make sure the balance is not affected and still the email is updated too?
Is it something that the SF has a built-in in the data access layer or do we (as the developer) have to take action for every update situation?
Thanks!
|
By StrataFrame Team - 1/25/2007
a) Yes, every column is updated. b/c) You have several options... the CollisionNotificationType property tells the business object how to handle it. If the property is set to RaiseEvent (default), then the concurrency exception will be found, the save process paused, a list of field collisions generated, the event is raised, the event args are set to tell the DAL which field value to save or overwrite (on a per-field basis), and the record is optionally resaved. This option is the default because the form automatically handles the event (set by the AutoHandleCollisions property on BaseForm). A pretty form is shown, informing the user that a data collision has occurred and asking them to choose the value. If the event is not handled, the default values of the event args allow the record to re-save and take the server values for each field that was conficting. You can also set the CollisionNotificationType property to ThrowException. This causes an exception to be thrown during the save process. You would then have to manually choose the values and resave the record(s).
|
By Ben Hayat - 1/25/2007
Hi Ben; Thanks for the reply!
If the property is set to RaiseEvent (default), then the concurrency exception will be found, the save process paused, a list of field collisions generated, the event is raised, the event args are set to tell the DAL which field value to save or overwrite (on a per-field basis), and the record is optionally resaved. This option is the default because the form automatically handles the event (set by the AutoHandleCollisions property on BaseForm).
So in this case the user can tell SF to only save email field (that she has changed) and not touch the balance field?
|
By StrataFrame Team - 1/25/2007
Correct, it will show them that the ballance field is different, but they can choose to take either the server's value or their value and then resave the record.
|
By Ben Hayat - 1/25/2007
Excellent! Man I think I'm getting to like this product
|
By Greg McGuffey - 1/25/2007
Ben (Strata), take a look at this post. It describes how to control the field names shown to the user. I.e. if your field is named user_email in the db, then it will also be named that in the BO and that is the name that will be shown on the concurrency form. This post describes how to change what the concurrency form shows.
|
By Greg McGuffey - 1/25/2007
Of course it would help if I actually posted the link!
http://forum.strataframe.net/Topic5006-6-1.aspx#bm5040
|
By Ben Hayat - 1/25/2007
Greg, your input is much appreciated. I think the time is coming where MicrFour needs to build a Knowledgebase system with all the questions and answers in a hierarchical format. I think the team is answering the same questions more than once. And to preserve the support resources, a knowledgebase would save time on each side?
Or should I put this proposal in the enhancement section?
|
By Greg McGuffey - 1/25/2007
A great idea. I was just thinking something like this earlier today, as I tried to find a post I'd read a while ago. I'd suggest posting in the enhancement area. This would let other uses (who may be ignoring this post) chime in with their $.02.
|
By Ben Hayat - 1/25/2007
I'd suggest posting in the enhancement area. This would let other uses (who may be ignoring this post) chime in with their $.02.
Done!
|
By Bradley Marston - 1/25/2007
I have a question reguarding concurrencyi have 2 business objects both use stored procedures to do an update if in my SP I have "SET NOCOUNT ON" it fires the form showning the user that a data collision has occurred and asking them to choose the value. could you explain why this is ?
|
By Trent L. Taylor - 1/25/2007
This is default behavior. If you do not want the form to pop up allowing the end-user to choose which value, you can turn off the AutoHandleCollisions property on the form and then manage the ConcurrencyException event yourself to take whatever action you would like.As for your SP, use the DDT to create stored procedures for you at least once, even if it is a test profile, so you can see what is expected on the StrataFrame CRUD settings side if you are creating them yourself.
|
By Bradley Marston - 1/26/2007
I understand that this is the default behavior, what i would like to know is whySET NOCOUNT effects the busines object and seems to cause the collisions
|
By Bradley Marston - 1/26/2007
I also seem not to be able to get back my GUID which is assigned bythe server with a call to "NEWID()" in my stored proc. Below is a zip file with the relevant files.
|
By StrataFrame Team - 1/26/2007
Bradley, The zip file didn't get attached, would you mind posting it again? The reason that SET NOCOUNT ON causes the business object to think that there is a concurrency exception is that the DAL tests the ExecuteNonQuery() return value to determine how many records were affected by the query. If SET NOCOUNT ON is used, then an UPDATE returns 0 records modified, so the business object thinks that no records were updated... meaning there was a concurrency excepton. SET NOCOUNT ON is fine for sprocs that return result sets or single values, but CRUD sprocs require the rowcount to determine whether or not they went through.
|
By Bradley Marston - 1/26/2007
Sorry I must have forgot to attach it.Seems like you cannot edit posts so here it is.
|
By Bradley Marston - 1/26/2007
Sorr lets try it one more time
|
By StrataFrame Team - 1/26/2007
You'll need to set your PrimaryKeyIsAutoIncremented property to True. This tells the DAL to consider the PK to be an output parameter and retrieve it after the record is inserted. You have to be using stored procedures to do a server assigned GUID PK that is auto-retrieved (so you're good to go). Also, if you want to remove your NULLIF(@CustomerID, '00000000-0000-0000-0000-000000000000'), you can set the Me.CustomerID = DBNull.Value in the SetDefaultValues() of the business object.
|
By Bradley Marston - 1/26/2007
I tried setting PrimaryKeyIsAutoIncremented to trueit does not seem to help. I still show customer_uid = '00000000-0000-0000-0000-000000000000' and debug output shows Direction: Input on customer_uid
|
By StrataFrame Team - 1/29/2007
The SqlDataSourceItem class is creates the paramters like this:
For Each lcField In QueryInfo.PrimaryKeyFields loParam = Me.CreateDbParameter(QueryInfo, lcField) loParam.ParameterName = "@" & lcField loParam.SourceColumn = lcField If QueryInfo.PrimaryKeyFieldIsAutoInc Then loParam.Direction = ParameterDirection.Output Else loParam.Direction = ParameterDirection.Input End If loReturn.Parameters.Add(loParam) Next
So, I'm not sure why the parameter direction is still Input. It should be Output. As for the GUID being initialized to 00000000-0000-0000-0000-000000000000, I believe I told you incorrectly to set the Me.CustomerID property directly. You'll have to go around the strong-typed property and set the field within the CurrentRow: Me.CurrentRow("CustomerID") = DBNull.Value. The property will not accept null values...
|
By Richard Keller - 1/29/2007
I've really been thinking about this concurrency issue within Strataframe and wonder if an option could be created to allow the where clause during the update to be dynamically assigned. Something like: Where Clause = Primary Key - This allows the update no matter what Where Clause = Modified Columns - This allows the update to only focus on columns that have the concurrency collision *** SLICK FEATURE *** Where Clause= Key and Updateable Columns where we can define an array of columns( or better yet have Strataframe Business Object Mapper allow us to define this !!!!! ) that are updateable to the Database. I personally do not like using Stored Procedures for updates because to enable Option # 2 you have to pass the Original Value and the Updated Value. This kills option 1 where I would like to update the record no matter what or I have two update procedures which is just as annoying to maintain. The sample previously of updating the Database Balance Column is what triggered my thinking because in my system the Balance is a summary column of detail records updated by triggers and I want the Business Object to display but never modify. I think that this would be fairly easy to implement, what do you guys think? Richard
|
By Greg McGuffey - 1/29/2007
Richard, how are you handling the calculated columns now, with the current BO technology?
(I'm going to have to deal with this soon )
|
By Richard Keller - 1/30/2007
That's part of the updateable setting that I mentioned above. I think that maybe the boys from Strataframe can enhance the framework here for this specific reason. Otherwise you'll have to use an UpdateStoredProcedure and code out the Database Computed Field.Rich
|
By Greg McGuffey - 1/30/2007
Well, I just noticed that you can mark a field as readonly in the BO mapper. It creates a readonly strongly typed property for the field. I'm wondering if this also means that the BO doesn't try to update the field during updates and if it skips the field if calling a sproc to update/create a record?
If so, then calculated columns are already handled
|
By Steve L. Taylor - 1/30/2007
Well, I just noticed that you can mark a field as readonly in the BO mapper. It creates a readonly strongly typed property for the field. I'm wondering if this also means that the BO doesn't try to update the field during updates and if it skips the field if calling a sproc to update/create a record?
All fields contained within the AllFieldsList() property will be persisted back to the database. This property is automatically created with the BO mapper and resides within the BOs respective designer. You can create a custom property, calculated field, that is not contained within this list and it will not be persisted. Please refer to the "Adding Custom Field Properties" topic in the help for further information. NOTE: In the next release 1.5.2 you will be able to exclude a specific field from updating.
|
By Greg McGuffey - 1/30/2007
NOTE: In the next release 1.5.2 you will be able to exclude a specific field from updating.
Excellent!
|
By Richard Keller - 2/17/2007
I upgraded to 1.6 and was looking for the 'updateable setting' metioned. Is it an enhancement of the read only property not to update back to the db now? Richard
|
By StrataFrame Team - 2/19/2007
Nope, every business object has a new property called FieldsToExcludeFromUpdate and FieldsToExcludeFromInsert... they should normally be the same, but you can set them to an array of field names that should be excluded from UPDATEs and INSERTs, respectively.
|
By Richard Keller - 2/19/2007
Ok, found it. That was smart so you could set a created by that only updates on Insert but does not ever get updated. Slick. You should put this in the Business Object Mapper as well in the future as it is a little tedious to type ( Sorry I'm a little lazy by nature ). Thanks for providing this and I can pull out the junk code i had to work around computed fields. Richard
|