Wednesday 28 May 2008

DataGridView - wrong row edited

When using the Edit functionality of a DataGridView it is easy to fall into the trap of selecting the wrong row to edit when running in a multi-user environment.

When user clicks row to edit you must store the ID of the row (not its index), then just prior to data-bind find the index of the selected ID in the data-source and set the EditIndex, this means if another user adds or removes rows in between the the current user clicking edit the correct row will be selected.

Tuesday 13 May 2008

SQL Left Join with Criteria

Query to get job title of staff or null if staff not assign a job-title:

 

SELECT     CORE_Staff.ID, CORE_Staff.JobTitleID, CORE_JobTitle.Name
FROM        CORE_Staff  LEFT JOIN CORE_JobTitle
                       ON CORE_JobTitle.ID = CORE_Staff.JobTitleID
where (CORE_JobTitle.Name='Driver') or (CORE_JobTitle.Name is null)

Rhino Mocks - Partial mock not calling base method

Had a problem where I was creating a partial mock then calling a method of the partial mock which was returning 0 (zero).

The base method was not being called even though no expectations had been setup.

The reason for this was that the ReplayAll (and VerifyAll) methods of Rhino Mocks was not being called.

Original code:

            _interestBiz = _mocks.PartialMock<InterestBiz>();
int baseDay = _interestBiz.GetBaseDaysFromAccount(account);
Assert.AreEqual(365, baseDay, "Incorrect base days");


Fixed code:



            _interestBiz = _mocks.PartialMock<InterestBiz>();
using (_mocks.Record())
{

}

using (_mocks.Playback())
{
int baseDay = _interestBiz.GetBaseDaysFromAccount(account);
Assert.AreEqual(365, baseDay, "Incorrect base days");



 



So even though no expectations were set Rhino Mocks needs to no this.

Thursday 1 May 2008

Good Rhino.Mocks introduction / tutorial

Good Rhino.Mocks introduction / tutorial here

C# Threading : Workers processing list

Using ThreadSafeQueue class as list of items to process.

Class used as a worker, takes list as parameter, creates a thread to run in.

public class MyWorker
{
private Thread _myThread;
public Thread WorkerThread
{
get { return _myThread; }
set { _myThread = value; }
}

ThreadSafeQueue<int> _listOfNumbers;
public string NumbersProcess = string.Empty;
int total=0;

public MyWorker(ThreadSafeQueue<int> listOfNumbers)
{
_listOfNumbers = listOfNumbers;
_myThread = new Thread(new ThreadStart(this.DoProcess));
}

public void DoProcess()
{
int _localInt=0;
do
{
if (_listOfNumbers.TryDequeue(out _localInt))
{
total = total + _localInt;
NumbersProcess = NumbersProcess + _localInt.ToString() + ", ";
}
} while ((!_listOfNumbers.NoMoreItems) ||
(_listOfNumbers.NoMoreItems) && (_listOfNumbers.Count > 0));
}
}



 



Calling process creates 5 workers then populates list, then waits for workers to finish processing:



//Queue to hold numbers to process
ThreadSafeQueue<int> listOfInts = new ThreadSafeQueue<int>();

//5 worker objects (threads)
MyWorker[] workers = new MyWorker[5];
for (int i = 0; i < workers.Length; i++)
{
workers[i] = new MyWorker(listOfInts);
workers[i].WorkerThread.Start();
}

//Populate list to process
for (int i = 0; i < 1000; i++)
{
listOfInts.Enqueue(i);
}

//Flag that no more items will be added to queue
listOfInts.NoMoreItems = true;

//Wait for workers to finish then display details
foreach (MyWorker worker in workers)
{
worker.WorkerThread.Join(); //Wait for worker to finish processing.
tbxDetail.Text=tbxDetail.Text+string.Format("Numbers processsed {0} \n",worker.NumbersProcess);
}
tbxDetail.Text = tbxDetail.Text + string.Format("\n\n");