Monday, 24 October 2011

Migrating from Subversion to Mercurial

This is an alternative way of migrating from SVN to Mercurial using HgSubversion as oppose to using convert extension. It allows you to push changes from local Mercurial repository to both Subversion and Mercurial during the transition period.

  • Install HgSubversion

hg clone http://bitbucket.org/durin42/hgsubversion/ <local-path>\hgsubversion

  • Add HgSubversion extension to your main hgrc file

[extensions]
hgsubversion = <local-path>\hgsubversion\hgsubversion

  • Clone existing subversion repository

hg clone http://<username>@<svn-project-path> <local-project-folder>

  • Edit project .hgrc file (/hg/.hgrc)

[paths]
default = http://<username>@<hg-remote-project-path>
svn = http://<username>@<svn-project-path>

  • Create new mercurial project in your remote Hg repository (see Rhodecode)
  • Pushing the project to remote mercurial repository

hg push

  • Pushing to subversion

hg push svn

If you’re using mercurial_keyring extension to store Hg passwords and your Svn username is the same as Hg one you need to have the same password for both.

Tuesday, 18 October 2011

Save window size & position in WPF

* Right Click on Settings.settings and Open With XML (Text) Editor

* Add Top, Left, Height, Width & WindowState settings

<Settings>
  <Setting Name="Top" Type="System.Double" Scope="User">
    <Value Profile="(Default)">50</Value>
  </Setting>
  <Setting Name="Left" Type="System.Double" Scope="User">
    <Value Profile="(Default)">50</Value>
  </Setting>
  <Setting Name="Height" Type="System.Double" Scope="User">
    <Value Profile="(Default)">800</Value>
  </Setting>
  <Setting Name="Width" Type="System.Double" Scope="User">
    <Value Profile="(Default)">1200</Value>
  </Setting>
  <Setting Name="WindowState" Type="System.Windows.WindowState" Scope="User">
    <Value Profile="(Default)">Normal</Value>
  </Setting>
</Settings>
* Add Settings property to App.xml
<Application.Resources>
    <properties:Settings x:Key="Settings" />
</Application.Resources>
* Add OnExit override to persist the settings when exiting application
protected override void OnExit(ExitEventArgs e)
{
    base.OnExit(e);
    Settings.Default.Save();
}
* Add Top, Left, Height, Width & WindowState bindings to your MainWindow
<Window x:Class="TestApp.MainWindow"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  Title="MainWindow"
  Top="{Binding Source={StaticResource Settings}, Path=Default.Top, Mode=TwoWay}"
  Left="{Binding Source={StaticResource Settings}, Path=Default.Left, Mode=TwoWay}"
  Width="{Binding Source={StaticResource Settings}, Path=Default.Width, Mode=TwoWay}"
  Height="{Binding Source={StaticResource Settings}, Path=Default.Height, Mode=TwoWay}"
  WindowState="{Binding Source={StaticResource Settings}, Path=Default.WindowState}">

Monday, 19 September 2011

RhodeCode open source HG (Mercurial) server

Download RhodeCode
* http://rhodecode.org/

Prerequisites
* Install Python 2.5 or later http://www.python.org/download/
* Add to PATH \Python27 and \Python27\Scripts folders
* Install SetupTools http://pypi.python.org/packages/2.7/s/setuptools/

Create \RhodeCode folder

Install RhodeCode
* easy_install rhodecode

Configure RhodeCode
* paster make-config RhodeCode production.ini
* paster setup-app production.ini

Run RhodeCode
* paster serve production.ini

Server is now running here http://localhost:8000

To change default host:port edit production.ini file

More info about installation and setup
http://packages.python.org/RhodeCode/installation.html
http://packages.python.org/RhodeCode/setup.html

Friday, 16 September 2011

C# Deep & Shallow Copy/Clone

class Program
{
  static void Main(string[] args)
  {
    var parent1 = new Parent() {Id = 1};
    parent1.Children = new List<Child>();
    parent1.Children.Add(new Child() { Name = "One" });
    parent1.Children.Add(new Child() { Name = "Two" });
    var parent2 = new Parent() { Id = 2 };
    parent2.Children = new List<Child>();
    parent2.Children.Add(new Child() { Name = "One" });
    parent2.Children.Add(new Child() { Name = "Two" });
    var parent3 = new Parent() { Id = 3 };
    parent3.Children = new List<Child>();
    parent3.Children.Add(new Child() { Name = "One" });
    parent3.Children.Add(new Child() { Name = "Two" });
    var parentShallowCopy = parent1.ShallowCopy();
    var parentDeepCopy = parent2.DeepCopy();
    var parentDeepClone = parent3.DeepClone();
    Console.WriteLine("ORIGINAL(1) : {0}", parent1);
    Console.WriteLine("SHALLOW COPY: {0}", parentShallowCopy);
    Console.WriteLine("ORIGINAL(2) : {0}", parent2);
    Console.WriteLine("DEEP COPY   : {0}", parentDeepCopy);
    Console.WriteLine("ORIGINAL(3) : {0}", parent3);
    Console.WriteLine("DEEP CLONE  : {0}", parentDeepClone);            
    parentShallowCopy.Children[0].Name = "Zero";
    parentDeepCopy.Children[0].Name = "Zero";
    parentDeepClone.Children[0].Name = "Zero";
    Console.WriteLine("");
    Console.WriteLine("ORIGINAL(1) : {0}", parent1);
    Console.WriteLine("SHALLOW COPY: {0}", parentShallowCopy);
    Console.WriteLine("ORIGINAL(2) : {0}", parent2);
    Console.WriteLine("DEEP COPY   : {0}", parentDeepCopy);
    Console.WriteLine("ORIGINAL(3) : {0}", parent3);
    Console.WriteLine("DEEP CLONE  : {0}", parentDeepClone); 
    Console.ReadLine();
  }
}
[Serializable]
class Parent
{
  public int Id { get; set; }
  public List<Child> Children { get; set; }
  public Parent ShallowCopy()
  {
    return (Parent)this.MemberwiseClone();
  }
  public Parent DeepCopy()
  {
    Parent other = (Parent)this.MemberwiseClone();
    other.Children = new List<Child>();
    this.Children.ForEach(x => other.Children.Add(x.DeepCopy()));            
    return other;
  }
  public override string ToString()
  {
    var sb = new StringBuilder();
    sb.AppendFormat("[Id:{0},Children:[", Id);
    Children.ForEach(x => sb.AppendFormat("{0},", x.ToString()));
    sb.Remove(sb.Length - 1, 1);
    sb.AppendFormat("]]");
    return sb.ToString();
  }
}
[Serializable]
class Child
{
  public string Name { get; set; }
  public override string ToString()
  {
    return string.Format("{0}", Name);
  }
  public Child ShallowCopy()
  {
    return (Child)this.MemberwiseClone();
  }
  public Child DeepCopy()
  {
    return (Child)this.MemberwiseClone();                        
  }
}
//extends classes that are marked [Serializable]
public static class ExtensionMethods
{        
  public static T DeepClone<T>(this T a)
  {
    using (MemoryStream stream = new MemoryStream())
    {
      BinaryFormatter formatter = new BinaryFormatter();
      formatter.Serialize(stream, a);
      stream.Position = 0;
      return (T)formatter.Deserialize(stream);
    }
  }
}

Tuesday, 13 September 2011

HG Mercurial Quick Setup Tutorial

Setting up Remote (build in) http server for multiple repositories

* Create Directory Structure

  - repo-root
   |- Project1.hg
   |- Project2.hg
   hgweb.config
   run.bat
 
* Edit hgweb.config as follows

  [collections]
  repos/ = .

  [web]
  style = gitweb
  push_ssl = false
  allow_push = *
 
* Edit run.bat as follows and run it

  hg serve --webdir-conf hgweb.config

Http Server is running on http://localhost:8000/ 
 

Setting up Remote Repository

* Create Folder /repo-root/Project1.hg
* Run hg init from within that folder


Setting up Local Repository

* Go to your local project directory /projects
* Clone remote repository locally

  hg clone http://localhost:8000/Project1.hg Project1

If you have an existing project and want to push it to remote repository

* Run hg push http://localhost:8000/Project1.hg

Or set default remote repository

* Create file /projects/Project1/.hg/hgrc
* Add this to file

  [paths]
  default =
http://localhost:8000/Project1.hg

* Now you can use hg push
 
Basic Commands

hg add (schedule files to be added to local repository)
hg commit (add files to local repository)
hg revert (revert changes to last commit)
hg push (push changes from remote repository)
hg pull (get changes from remote repository)
 

For more info look at Joel Spolsky Hg Init Mercurial Tutorial

Thursday, 8 September 2011

Simple XML based C# Database

public class DatabaseMgr
{
  public Database Database { get; set; }
  private static DatabaseMgr instance;
  private DatabaseMgr() { }
  public static DatabaseMgr Instance
  {
    get
    {
      if (instance == null)
      {
        instance = new DatabaseMgr();
      }
      return instance;
    }
  }
  //use temp path
  private static string PATH = Path.Combine(Path.GetTempPath(), "UserDatabase.xml");
  public void Reload()
  {
    if (File.Exists(PATH))
    {
      XmlSerializer xs = new XmlSerializer(typeof(Database));
      using (TextReader reader = new StreamReader(PATH))
      {
        Database = (Database)xs.Deserialize(reader);
        reader.Close();
      }
    }
    else
    {
      Database = new Database();                
    }
  }
  public void Save()
  {
    XmlSerializer xmlSerializer = new XmlSerializer(typeof(Database));
    using (TextWriter writer = new StreamWriter(PATH))
    {
      xmlSerializer.Serialize(writer, Database);
      writer.Close();
    }
  }
}
[Serializable]
public class Database
{
  public Database()
  {
    Users = new List<User>();            
  }
  [XmlArray]
  [XmlArrayItem(ElementName = "User")]
  public List<User> Users { get; set; }
}
[Serializable]
public class User
{
  [XmlElement]
  public string Name { get; set; }
  [XmlElement]
  public int Age { get; set; }
}
[Test]
public void Test()
{
  DatabaseMgr.Instance.Reload();
  DatabaseMgr.Instance.Database.Users.Add(new User() { Name = "John", Age = 25 });
  DatabaseMgr.Instance.Save();
  foreach (var user in DatabaseMgr.Instance.Database.Users)
  {
    Console.WriteLine("{0}=>{1}",user.Name,user.Age);
  }
}

Tuesday, 30 August 2011

C# Log4Net configuration for multiple processes with date rolling

This example uses MinimalLock locking Model to allow multiple processes to write to the same file

<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
  <file value="Log\\MyApp.log"/>
  <appendToFile value="true"/>
  <rollingStyle value="Date"/>
  <datePattern value=".yyyyMMdd"/>
  <maxSizeRollBackups value="7"/>
  <staticLogFileName value="true"/>
  <threshold value="INFO"/>
  <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />                       
  <layout type="log4net.Layout.PatternLayout">
    <conversionPattern value="%d [%t] %-5p %c.%M():%L - %m%n"/>
  </layout>
</appender>

Click here for more detailed post about Log4Net configuration in console apps

Friday, 26 August 2011

C# Send email with embedded image

string mailserver = "mymailserver";
            
string subject = "Email with picture";
string body = "<html><body><h1>Picture</h1><br><img src=\"cid:Pic1\"></body></html>";
string to = "to@email.com";
string from = "from@email.com";
string imagePath = @"c:\temp\myimage.png";
            
AlternateView view = AlternateView.CreateAlternateViewFromString(body, null, MediaTypeNames.Text.Html);
LinkedResource pic = new LinkedResource(imagePath, MediaTypeNames.Image.Gif);
pic.ContentId = "Pic";
view.LinkedResources.Add(pic);
            
MailMessage m = new MailMessage();
m.AlternateViews.Add(view);
            
m.From = new MailAddress(from);
m.To.Add(new MailAddress(to));
m.Subject = subject;
SmtpClient client = new SmtpClient(mailserver);
client.Send(m);

Friday, 19 August 2011

SQL Delete in batches based on date

This is a sample how to delete data in batches to avoid large transaction log. This is a simpler version of this example when I used 2 tables.

DECLARE @MyTable TABLE 
( 
	Id int,
	DateUpdated DATETIME
)
INSERT INTO @MyTable
SELECT 1,DATEADD(d,-1,GETDATE())
UNION SELECT 2,DATEADD(d,-2,GETDATE())
UNION SELECT 3,DATEADD(d,1,GETDATE())
UNION SELECT 4,DATEADD(d,2,GETDATE())
UNION SELECT 5,DATEADD(d,-3,GETDATE())
UNION SELECT 6,DATEADD(d,-2,GETDATE())
UNION SELECT 7,DATEADD(d,-4,GETDATE())
DECLARE @date DATETIME
SET @date = GETDATE()
PRINT CONVERT(CHAR(19),GETDATE(),120) +' Deleting data in batches' 
WHILE (Exists(SELECT 1 FROM @MyTable WHERE DateUpdated < @date))
BEGIN TRY    
    BEGIN TRAN     
       PRINT CONVERT(CHAR(19),GETDATE(),120) +'   Deleting 2..'   
       DELETE TOP(2) @MyTable FROM @MyTable WHERE DateUpdated < @date
    COMMIT TRAN 
END TRY
BEGIN CATCH 
    ROLLBACK
END CATCH
--SELECT * FROM @MyTable

Friday, 12 August 2011

Retry class implemented in functional C#

public class Retry
{
  public static ILog _log = LogManager.GetLogger(MethodInfo.GetCurrentMethod().DeclaringType);
  int _retryAttempts = 3;
  int _retryWaitSeconds = 1;
  public Retry() { }
  public Retry(int retryAttempts, int retryWaitSeconds)
  {
    _retryAttempts = retryAttempts;
    _retryWaitSeconds = retryWaitSeconds;
  }
  public void Execute(Action action)
  {
    int attempt = 0;
    while (attempt++ < _retryAttempts)
    {
      try
      {
        if (_log.IsDebugEnabled)
        {
          _log.DebugFormat("Retry attempt {0}/{1}", attempt, _retryAttempts);
        }
        action();
        return;
      }
      catch (Exception e)
      {
        if (attempt >= _retryAttempts)
        {
          _log.ErrorFormat("Retry failed with {0} attempts", _retryAttempts);
          throw e;
        }
        int wait = _retryWaitSeconds * attempt;
        _log.Warn(string.Format("Retry attempt {0}/{1} failed, waiting {2}s", attempt, _retryAttempts, wait), e);
        Thread.Sleep(1000 * wait);
      }
    }
  }
  public TResult Execute<TResult>(Func<TResult> func)
  {
    int attempt = 0;
    while (attempt++ < _retryAttempts)
    {
      try
      {
        if (_log.IsDebugEnabled)
        {
          _log.DebugFormat("Retry attempt {0}/{1}", attempt, _retryAttempts);
        }
        return func();
      }
      catch (Exception e)
      {
        if (attempt >= _retryAttempts)
        {
          _log.ErrorFormat("Retry failed with {0} attempts", _retryAttempts);
          throw e;
        }
        int wait = _retryWaitSeconds * attempt;
        _log.Warn(string.Format("Retry attempt {0}/{1} failed, waiting {2}s", attempt, _retryAttempts, wait), e);
        Thread.Sleep(1000 * wait);
      }
    }
    throw new Exception("Retry failed");
  }
}
[TestFixture]
public class TestRetry
{
  [Test]
  public void Test()
  {
    new Retry(3, 1).Execute(SuccessAction);
    try
    {
      new Retry(3, 1).Execute(FailureAction);
    }catch(Exception ex)
    {
      Console.WriteLine("Failed");
    }
    Console.WriteLine(new Retry(3, 1).Execute(() => ComplexAction("1", "2")));
    Console.WriteLine(new Retry(3, 1).Execute(() => ObjectAction("John")).ToString());
    Func<Person> func = () =>
    {
      return new Person() { Name = "John" };
    };
    Console.WriteLine(new Retry(3, 1).Execute(func));
  }
  private void FailureAction()
  {
    Console.WriteLine("{0}: Failed", DateTime.Now);
    throw new Exception("Failed Exception");
  }
  private void SuccessAction()
  {
    Console.WriteLine("{0}: OK", DateTime.Now);
  }
  private string ComplexAction(string a, string b)
  {
    return String.Format("{0} {1}", a, b);
  }
  private Person ObjectAction(string name)
  {
    return new Person() { Name = name };
  }
}
class Person
{
  public string Name { get; set; }
  public override string ToString()
  {
    return "My name is : " + Name;
  }
}