Monday, June 28, 2010

Compare two object's values

Recently we encounter an event that receives two objects and we wanted to compare their values (before and after of a column 'changing' event on a datatable). Using '==' doesn't do the work because the implementation of '==' in object compares the actual reference and not the values.

This simple method does the work.

static bool CompareObjectsValues(object a, object b)
{
if (a.GetType()!=b.GetType() 
|| !(a is IComparable) || !(b is IComparable))
return false;

IComparable valA = a as IComparable;
IComparable valB = b as IComparable;

return (valA.CompareTo(valB) == 0);

}


Full sample to show the problem and test:
static bool Compare(object a, object b)
{
return (a == b);
}

static void Main(string[] args)
{
object a = new object();
object b = new object();

DateTime d1 = new DateTime(2010, 6, 27);
DateTime d2 = new DateTime(2010, 6, 27);

a = d1;
b = d2;

object c = a;


//returns 'true' -> same reference
Console.WriteLine(Compare(a , c)); 
//returns 'false'-> same value but not same reference -> problem
Console.WriteLine(Compare(a , b)); 
//returns 'true' -> compares values and not references
Console.WriteLine(CompareObjectsValues(a, b));

}


That's it...
Diego

Thursday, June 17, 2010

Working with LayoutEngine

When you developing your custom controls sometime it requires a certain behavior or graphical representation of it child controls .
In this case you Control have a property called LayoutEngine
Example below shows you how to implement your LayoutEngine 

     public class DemoPanel : Panel
    {
        private bool m_CustomLayout = false;
        private DemoPanelLayout layoutEngine = new DemoPanelLayout();

        public DemoPanel() { }
        public bool CustomLayout
        {
            get { return m_CustomLayout; }
            set { m_CustomLayout = value; }
        }
        public override LayoutEngine LayoutEngine
        {
            get
            {
                return layoutEngine;
            }
        }
      }
Now for the custom LayoutEngine implementation


    public class DemoPanelLayout : LayoutEngine
    {
        public override bool Layout(
            object container,
            LayoutEventArgs layoutEventArgs)
        {

            Control parent = container as Control;
            if (((parent as DemoPanel).CustomLayout))
            {           
             Rectangle parentDisplayRectangle = parent.DisplayRectangle;
             Point nextControlLocation = parentDisplayRectangle.Location;
           
            foreach (Control c in parent.Controls)
            {               
                if (!c.Visible)
                {
                    continue;
                }
                if (nextControlLocation == parentDisplayRectangle.Location)
                {
                    nextControlLocation.Y += c.Margin.Top;
                    nextControlLocation.X += c.Margin.Left;
                }
              
                c.Location = nextControlLocation;
                if (!((c.Location.X + c.Width + c.Margin.Left)> (parent.Width - c.Width-c.Margin.Left)))
                {
                    nextControlLocation.Offset(c.Width+c.Margin.Left, 0 );
                }
                else
                {
                    nextControlLocation.X = parent.Left+c.Margin.Left;
                    nextControlLocation.Offset(0,c.Height+c.Margin.Top);
                }               
             }
            }
                       
            return false;
        }
    }


In example above DemoPanel's LayoutEngine will check the CustomLayout property
and order child controls as tabled view .

Tuesday, June 15, 2010

Paging in SQL 2005

Suppose that you need to reduce the load of traffic between the Microsoft SQL 2005 DB 
and application in case of client \ server application also reduce the load of traffic between 
client and application server. One of the known methods is Paging .
In a simple example below, I'll show you how to implement Paging method at SQL 2005 
server side.
Create and fill temporary table #someTable for example :
        
              create table #someTable(RecordKey int,FieldA int, FieldB nvarchar(50))
              insert into #someTable(RecordKey,FieldA , FieldB)values(1,5,'a')
              insert into #someTable(RecordKey,FieldA , FieldB)values(2,4,'ab')
              insert into #someTable(RecordKey,FieldA , FieldB)values(3,3,'abc')
              insert into #someTable(RecordKey,FieldA , FieldB)values(4,2,'abcd')


We'll use page size=2 ,FieldA as sort field and  page number = 1


               DECLARE @PageSize INT
              DECLARE @RequestPageNumber INT

               set @RequestPageNumber = 1
               set @PageSize = 2

              DECLARE  @FromKey INT
              DECLARE @ToKey INT

              set @ToKey = (@PageSize * @RequestPageNumber)
              set @FromKey = @ToKey - @PageSize + 1;      
              
;WITH SortedTable As
(
  SELECT
                             ROW_NUMBER() OVER (ORDER BY FieldA) as RowNumber,
                             RecordKey,
     FieldA,
     FieldB
  FROM #someTable
                       )
                         SELECT
                           RecordKey,
  FieldA,
  FieldB
                         FROM SortedTable
  WHERE RowNumber BETWEEN @FromKey AND @ToKey


The result as you can see two rows sorted by FieldA :

The example showed us the MS SQL 2005 server side implementation of paging technique
the application server/client paging techniques is another post issue ,but the common idea
identical to this one that implemented here.

Sunday, June 13, 2010

Simple example of how to expose .net controls to VB6

There's already a lot of discussions on iNet on this theme i'll just show you on simple
example how to expose your .Net Controls as COM to other development
environment (in our case VB6 as example).

Create your control library and make it com visible as in picture below

Because we do not have setup for now and for test we should register our library as COM
check the register for COM option to register it

Create some control and make it com visible also give it a ProgId to expose it to out world


Build the project and let test our control in VB6
Create new vb6 exe project . To add our control dynamically onto the form we will use
the VBControlExtender and code looks like that :


       Option Explicit
       Dim WithEvents objExt As VBControlExtender

       Private Sub Form_Load()
          'adding our control licens to licences collection
           Licenses.Add "InteropControlLib.DotNetControl", "ewrinvcmcoe"
           'adding the control to Form
            Set objExt = Me.Controls.Add("InteropControlLib.DotNetControl", "DotNetControl1", Me)
            objExt.Visible = True
       End Sub

Run the test project and wuala, you got .net control on vb6 form :


Those of you who found this article interesting and want to find more
check out links below :
 COM Interoperability in .NET Framework Applications
 COM Interop



Thursday, June 10, 2010

Executing dtsx on Microsoft SQL 2005 Express with schedule

Let say you need to run scheduled DTS package on Microsoft SQL 2005 Express and
as you probably know there is no SSIS and Agent Services in Microsoft SQL 2005 Express
edition but you can do this job actually very easy :

1.
   Assure that you do have the DTExec util, it should be in
   C:\Program Files\Microsoft SQL Server\90\DTS\Binn folder ,
   if you do not have one means you should install SQL Toolkit .

2.
   Next step is to make a batch file to run the DTS package.
   Create batch file with DTExec formatted command for example
             setlocal
             Set upPath=[Some folder path where you have your package or whatever ]
             Set logFileName=DTS_Batch_Log

             cd "C:\Program Files\Microsoft SQL Server\90\DTS\Binn"

             set startDate=%date%
             set startTime=%time%

             set sdy=%startDate:~10,4%
             set sdm=%startDate:~4,2%
             set sdd=%startDate:~7,2%
             set sth=%startTime:~0,2%
             set stm=%startTime:~3,2%
             set sts=%startTime:~6,2% 0

             DTExec.exe /F "%upPath%\DTS\[MyDTSName].dtsx"
             /MAXCONCURRENT " -1 " /CHECKPOINTING OFF
             /SET "\Package.Variables[My DTS Variable name].Value";
             "[Here is comes the My DTS Variable  value]"
              >> "%upPath%\%logFileName%_%sdy%.%sdm%.%sdd%-%sth%.%stm%.log"
             IF %ERRORLEVEL% == 0 GOTO [Some label ] ELSE GOTO End
             : Some label
                   your code comes here
             : End
                  
   The example above shows how to run DTSX Package from File and Log
   the results of execution to some log file.

3.
   Last step is schedule and Yes there is one in Windows it called " Scheduled
   Tasks" you could find it in System Tools – just create one with call of the batch
   that you created earlier to run dtsx packages.

And that's all you need for the job to be done ;)...

Monday, June 7, 2010

SqlBroker clean up

Testing SqlBroker for the 1st time outside the development environment I realized I did not define the Authorization attribute when creating the objects (messagetype, contract & services) see Asynchronous triggers using SQL Broker for more details.

This mistake filled the queue with over 300,000 messages that were not going anywhere even after I fixed the Authorization.

Good thing I found this on test environment which allowed me to run a short script that cleans up those messages without worrying about the consequences.

BTW, if you were thinking of dropping the objects and rebuild them...tried that - got a weird out of memory message from SQL Server.

Here is the script:

declare @conversation uniqueidentifier

while exists (select 1 from sys.transmission_queue )

begin

set @conversation = (select top 1 conversation_handle from sys.transmission_queue )

end conversation @conversation with cleanup

end


Till next time...
Diego