StrataFrame Forum

How to Prevent Concurrent Data Collisions

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

By Ger Cannoll - 3/16/2012

If two users modify data at the same time ( e.g. user 1 Reads data into a BO, Changes It, Users 2 reads same Data into a BO, User 1 then saves the BO, and then User 2 Attempts to Save the same data), a message comes up:

Data Collision... Another user made changes to the same record..choose the changes to accept  (MyValue or Server Value)

Now, this is fine most of the time (say for Master File Changes)

However, If say an Invocie is being modified in this way, I NEVER want the second user to have their changes accepted. In this case, I would prefer if an error was raised and a notification to this effect ended up in the BrokenRules Collection

In my BusinessObject, I would like to do something like:

if (DataCollision = true) {this.AddBrokenRule("XXX", "Another User has just amended the transaction ");}

and I do not want the user to have the option to choose what is to be done.

 

By Ivan George Borges - 3/17/2012

Hi Ger.

What I do is to handle collision myself, then I have control to do whatever I want. To accomplish this, on my Base BO, I handle the ConcurrencyException and then call my own method to take care of it:

    Private Sub _PFNBaseBO_ConcurrencyException(ByVal e As MicroFour.StrataFrame.Data.ConcurrencyExceptionEventArgs) Handles Me.ConcurrencyException
        '-- handle concurrency with our own Collision form
        Me.HandleConcurrency(e)
    End Sub


Then, I use my own dialog to show collisions, for the fields I want, formatted in the way I want. You will find all collisions in the e.Collision Concurrency Exception Event Argument.
Also, I guess you can just set the BO CollisionNotificationType at form level to ThrowException, which will have all information about what happened in the collision and you can deal with that.
There are some good posts on collisions in the Forum, here are some links to get you started:

http://forum.strataframe.net/FindPost27465.aspx
http://forum.strataframe.net/FindPost15123.aspx
By Ger Cannoll - 3/18/2012

Hi Ivan. Thanks for replying. I  tam taking your  advice and Put some code in to my Base Class for BO as follows:

protected override void ConcurrencyException(MicroFour.StrataFrame.Data.ConcurrencyExceptionEventArgs e)        

//-- Hhandle concurrency with our own Collision i.e. Want to add an error to Errors Collection

{

   this.AddBrokenRule(this.PrimaryKeyField, "Another user has amended this item at the same time");

}

However, above gives a Compile error (...BusinessLyer.ConcurrencyException is not a function)

I must have syntax wrong ??

Also, other than just setting the AutoHandleCollisions on the form to false, it there amything else I neeed to do. If there is a Concurrency problem, all I want to do is add this to the BrokenRules collection and not show any other form, but definitiely NOT to save the data. Presumably if I have added a line to the BrokenRules, the form will NOT be saved

By Ivan George Borges - 3/19/2012

Hi Ger.

C# is not my "mother tongue", but I guess it should be something like:

private void YourBaseBO_ConcurrencyException(MicroFour.StrataFrame.Data.ConcurrencyExceptionEventArgs e)
     {
         this.AddBrokenRule(this.PrimaryKeyField, "Another user has amended this item at the same time");
         e.ResaveRecord = False;
     }

The e.ResaveRecord will take care of cancelling the Save.
By Ger Cannoll - 3/19/2012

Hi Ivan. Thanks for that. I can now get it to compile .

I am still having two issues.

1. Even though I have code to AddbrokenRules, it does not seem to be doing this. If there is a collision, it is not now showing the SF Collision Form and it is not saving (which is what I want) but I want to update the BrokenRule collection so that all errors are seen from the same place

2. In the above, for testing, I was setting the propeties on the Form Instances , rather than on a subclassed form, as I am having difficulty setting a Property on a SubClassed form. I have previosuly  added functionality to other controls successfully , but this is the first time I am trying to add functionality to a subclassed Form. The AutoHandleCollisions = false does not seem to be doing anything.  My Code to subclass the form is:

    public class StandardForm : MicroFour.StrataFrame.UI.Windows.Forms.StandardForm

    {

         private voidInitializeComponent()

        {

           this.SuspendLayout();

           //

           // StandardForm

           //

           this.ClientSize = new System.Drawing.Size(294,274);

           this.Name = "StandardForm";

           this.Load += newSystem.EventHandler(this.StandardForm_Load);

           this.AutoHandleCollisions = false;

           this.ResumeLayout(false);

 

        }

 

        private voidStandardForm_Load(object sender, EventArgs e)

        {

        }

    }

By Ivan George Borges - 3/21/2012

1. Even though I have code to AddbrokenRules, it does not seem to be doing this. If there is a collision, it is not now showing the SF Collision Form and it is not saving (which is what I want) but I want to update the BrokenRule collection so that all errors are seen from the same place


If you let it try resaving, after adding the broken rule, won't it work the way you want?


2. In the above, for testing, I was setting the propeties on the Form Instances , rather than on a subclassed form, as I am having difficulty setting a Property on a SubClassed form. I have previosuly  added functionality to other controls successfully , but this is the first time I am trying to add functionality to a subclassed Form. The AutoHandleCollisions = false does not seem to be doing anything.  My Code to subclass the form is:


Sorry, I am a bit confused on this one. Would you like to produce a small simple sample application of what you want to accomplish? Then it could be easier to follow it.
By Ger Cannoll - 3/21/2012

Hi Ivan.

I will do up a small project to iluustrate both issues.
By Ger Cannoll - 3/21/2012

Hi Ivan.

I have attached a Sample Project to illustrate the second problem I am having. Just trying to Subclass a StratatFrame Form and have the AutoHandleCollisions set to False in my SubClass

In the Sample, My Subclass is called MyForm, and I have a line in it with this.AutoHandleCollisions = false

When I run up my Form (Form2, called from Form1) , I have a button whcih displays a messagebox, indicating what the AutoHandleCollisions property is. It is saying True, even though my BaseClass has set it to false. (This may very well be the result of my Inexperience of Subclassing a Form and I may have left out something or not done it the correct way.

(Sample project based on the Customers Tbale in the StartaFrame sample database)
By Ger Cannoll - 3/25/2012

Hi Ivan.

Any update on this. (Trying to subclass a and have the AutoHandleCollisions set to False in my SubClass...see attached Sample on laste thread)
By Ivan George Borges - 3/26/2012

Hi Ger.

I tried to have a look at your sample but couldn't find out how to solve your problem. As I told you, I do vb.net and tried to Google how the C# inheritance should behave, but didn't get to a conclusion why yours is not working. In my solutions, my base form is set with AutoHandleCollisions to False and all inherited forms from it also has it like that.

So, I hope someone will jump in and clarify this for you.
By Fabian R Silva, - - 3/27/2012

I not tried the example, but can put the code after initialicecomponent?, something like this in the constructor:
public CRUDForm(SomeDTO someDTO) : base(someDTO)
{
    InitializeComponent();
    PropertyToChange = value;        
}
This have to work.
By Ger Cannoll - 3/28/2012

Hi Fabian. Thanks for replying.

I have really simplified MySubClass, and taken SF out of the equation, so this must be something silly in the way I am coding the subclass. My Code now is: (Just trying for instance to have all forms DarkGreen ) 

public class MyFormNotSF: System.Windows.Forms.Form

        {

          public voidInitializeComponent()

          this.BackColor = System.Drawing.Color.DarkGreen; }

        }

and in my Form to use the SubClass:

public artial class Form3 : MyFormNotSF  ........

 

 

By Ger Cannoll - 4/4/2012

Hi Ivan. I am back to the concurrency issue  now. I have resolved being able to SubClass a Form (Uing C#) , thanks to another thread.

To Recap. If there is a DataColission, I want to add the fact to the BrokenRules collection and display a Message indicating this, and not allow the save. I have atached a Sample App. I have done the following in the App:

In my Base Form, Set AutoHandleCollisions to False

In the BO, left the CollisionNotificationType to RaiseEvent (The Default)

In My Base BO, put code into the BO_ConcurrencyException event as follows:

1. AddBrokenRule message

2. e.ReSaveRecord = true  (Set the flag so it will attempt to Resave the data) 

3.  this.Save  (Attemp to Save the record, which then should trigger the broken rules)

What is happening is that , for the Concurrency problem  record, The Broken Rule is NOT being displayed . It does not save the record (which is fine) but I want it to display the BrokenRules to indicate to the user that there has been a problem.
By Ivan George Borges - 4/4/2012

Hi Ger.

I have changed your sample project and am posting it here back to you.
I have created a new Base BO and added some code to it to demonstrate how you can accomplish what you are looking for.
If you feel like it, have a look at the help file under "Application Framework" -> "Business Layer" -> "Common Business Object Tasks" ->"Creating and Checking Business Rules" to get the a better understanding of the flow.

Hope it helps. Wink
By Ger Cannoll - 4/4/2012

Hi Ivan.

I have downloaded and extracted the amnded sample and it does what I want. Many thanks for putting in the time.

I will need to have a look at the code to get an understanding of how it works.
By Ivan George Borges - 4/5/2012

You're welcome, Ger. Cool
By Ger Cannoll - 4/6/2012

Hi Ivan. I am now trying to incorporate your suggestions into my live project  and am having two problems:

1. In the Base SubClass, when I try to add InitializeComponent into each constructor, it comes up with a error in the compiler (InitializeComponent does not exist in the current context)..... now if I comment the line out, it seems to work ok... Do I need this line in ?

2. In my actaul BO classes, I need to have specific code in the CheckRulesOnCurrentRow, so I want to run the Base Code in my subclass. When I put in  base.CheckRulesOnCurrentRow()  or base.CheckRulesOnCurrentRow(CheckRulesEventArgs e) I  get a complier message --> CheckRulesOnCurrentRow can only appear on the left hand side of += or -=

     
By Ger Cannoll - 4/16/2012

Hi. I am really stuck on this as I cannot seem to get the Base Code running from my specific CheckRulesOnCurrentRow

Any feedback appreciated
By Ger Cannoll - 4/25/2012

Anbody ?
By Trevor Hendricks - 4/26/2012

Ger, I'm new to SF but this is what I use.

public BaseBO()  : base()
        {
            InitializeComponent();
            //-- Add the necessary handlers
            this.AddHandlers();
        }

        public BaseBO(IContainer container)
            : base()
        {
            //This call adds the component to the given container.
            Container.Add(this);
            //This call is required by the Component Designer.
            this.InitializeComponent();
            //-- Add the necessary handlers
            this.AddHandlers();
        }

        /// <summary>
        /// Initializes a new instance of the BusinessObject1 class.
        /// </summary>
        /// <param name="info">The SerializationInfo for the object to create.</param>
        /// <param name="context">The StreamingContext for the source stream.</param>
        protected BaseBO(SerializationInfo info, StreamingContext context)
            : base(info, context)
        {
            //This call is required by the Component Designer.
      this.InitializeComponent();
      //-- Add the necessary handlers
      this.AddHandlers();
        }

        /// <summary>
     /// Adds the necessary handlers for the BaseBO class.
     /// </summary>
     /// <remarks></remarks>
     private void AddHandlers()
     {
      this.CheckRulesOnCurrentRow += BaseBO_CheckRulesOnCurrentRow;
      this.SetDefaultValues += BaseBO_SetDefaultValues;
     }

HTH

Trevor
By Ger Cannoll - 5/2/2012

Hi Trevor. Thanks for that whcih helped a lot.

Part of my problem was that when I was initially creating my BO subclasses, I coded it all from scratch. I have now gone back in and recreated them but used the SF template (I did not think it was necessary to use these if creating a Subclass). For this reason I thin, it was missing out bits , paertculalry in IitializeComponent.

Anyway, seem to have it workong now, so many thanks