StrataFrame Forum

Concurrency question

http://forum.strataframe.net/Topic6191.aspx

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 Smile
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! Blush



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 concurrency

i 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 why

SET 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 by

the 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 true

it 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 Smile )
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 BigGrin
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