Thursday, 4 March 2010

Upgrade to Visual Studio 2010 Release Candidate

After using VS2010 Beta for a while, I upgraded it to RC recently. It seems to be more stable and robust. So here are steps for upgrade:

1. Uninstall VS 2010 Beta
2. Install VS 2010 RC
3. Run VS2010 RC setup again and choose Repair
4. Download and install Hotfix KB980610

UPDATE March 7, 2010:
5. Download and install Hotfix KB980920

Deep cloning object in C#/.NET

I was asked recently to write a generic method for deep cloning of a complex object. The object contains references to other objects, collections, which contain references to many other objects and collections. The method was supposed to work on both platforms: .NET 3.5 (or higher) and Silverlight.

While googling I found a good post listing different approaches for cloning
C# Object Clone Wars

Last technique described in that blog points to Copyable Framework - generic framework for copying/cloning any objects using method extensions

The framework, written by Håvard Stranden addresses most of my requirements, except one: it does not work on Silverlight.

I came up with a simple method that serializes the original object and deserializes it to a cloned copy of it. It can be used as an extension or by implementing IClonable interface:

public static class ObjectExtensions
{
  public static T Clone<T>(this object original)
  {
    T cloned;
    using (MemoryStream stream = new MemoryStream())
    {
      DataContractSerializer serializer = new DataContractSerializer(typeof(T));
      serializer.WriteObject(stream, original);
      stream.Position = 0;
      cloned = (T)serializer.ReadObject(stream);
    }
    return cloned;
  }
}


* This source code was highlighted with Source Code Highlighter.

Tuesday, 9 February 2010

WCF Serialization Tips

Here are a few tips on how to improve WCF performance and traffic by simple putting the right attributes on your serializable classes:


1. "Avoid inferred data contracts (POCO). Always be explicit and apply the DataContract attribute" (C) Juval Löwy
2. "Use the DataMember attribute only on properties or read-only public members" (C) Juval Löwy
3. Mark [DataMember] only properties, that DO have to be serialized. Avoid marking calculated properties as DataMember
2. Consider using (IsReference = true) on classes to avoid data duplication and circular references.
3. Use short (one or two letters) Name on classes and properties to significantly reduce traffic. (C) Eyal Vardi
4. Specify short Value for EnumMember
5. Use parametrized DataContract property for generic classes
6. Use (EmitDefaultValue=false) on properties to reduce traffic

Sample:

[DataContract(Name="CT")]
  public enum CustomerTypes
  {
    [EnumMember(Value = "I")]
    Internal,
    [EnumMember(Value = "E")]
    External,
    [EnumMember(Value = "U")]
    Unknown
  }

  [DataContract(IsReference = true, Name = "B{0}")]
  public class BusinessBase<T>
  {
    T Id { get; set; }
  }

  [DataContract(IsReference = true, Name = "C")]
  public class Customer : BusinessBase<int>
  {
    [DataMember(Name="C", EmitDefaultValue=false)]
    public CustomerTypes CustomerType { get; set; }

    [DataMember(Name = "N", EmitDefaultValue = false)]
    public string Name { get; set; }

    [DataMember(Name = "P", EmitDefaultValue = false)]
    public Customer ParentCustomer { get; set; }

    public bool IsGoodCustomer
    {
      get
      {
        return this.CustomerType == CustomerTypes.Internal || this.CustomerType == CustomerTypes.External;
      }
    }

  }


* This source code was highlighted with Source Code Highlighter.

Wednesday, 4 November 2009

System.Data.DataRow indexer complexity

Have you ever wonder what is the time complexity of accessing DataRow by column name? Unfortunately, this information is not specified on MSDN.

So the obvious answer would be O(n). We might think that there is iteration on data columns and in worst case it would iterate on all of them.

The actual answer can be discovered by looking on System.Data.dll using Reflector. We'll see there, that there is an access to Hashtable of column names by name, which obviosly take O(1).

So the overall complexity of the following would be O(1).

object data = row["CUSTOMER"];

Wednesday, 30 September 2009

How to retrieve new row data from INSERT using Oracle DataAccess

Answering a question on StackOverflow:

"I am using Oracle database server with Oracle DataAccess client. What I need to do is INSERT a new row of data, then retrieve the auto-generated ID field of the newly-created row for another INSERT command, immediately following. What is the best way to do this?"

Answer:
1. Modify the INSERT query by adding RETURNING keyword
"INSERT INTO table_name (column_name1, column_name2) VALUES ('val1', 'val2')
RETURNING module_id INTO :column_id"


* This source code was highlighted with Source Code Highlighter.

2. Add a bind variable to your OracleCommand named "column_id"
3. Take its value after the command is executed