Thomas's profileBlogsBlogLists Tools Help

Tom's Webspace for .NET Developers

protect the world from the scum of linux

Blogs

08 March

Database Mirroring

What is mirroring?

 

Mirroring constantly synchronizes the transaction log of a mirror server with the transaction log of a principal server. The synchronization can be either synchronal to enable high availability, or asynchronal to enable high performance.

If set to high availability, a witness server is required. this can be either the principal server itself, or a 3rd server. If a 3rd server is chosen, this ensures more security in case of a failure.

To configure mirroring, the mirror server must restore a backup of the principal with NORECOVERY mode. Thus you cannot access the mirror database directly, since it remains in recovery mode. But you can create a snapshot of the mirror to read data. Also, the database must set to full recovery mode. (Note: if you want to have a full working copy of a database, then log shipping or replication is your choice over mirroring)

Mirroring requires endpoints (TCP or HTTP) for the principal, the witness and the mirror server. The endpoints are configured automatically, when you create mirroring in the properties options of the database.

The main purpose for mirroring however is to have a high available backup in case of an error of the principal server.  In High Availability mode, a failover is automatically performed to the mirror, when a failure occurs on the principal. Otherwise you need to launch a failover manually:

ALTER DATABASE <mirror_database> SET PARTNER FORCE_SERVICE_ALLOW_DATA_LOSS

07 March

SQL Server Management Studio: Copy Database

When you right click any Database in the SSMS, you can access the Copy Database tool:

CopyDataBase

This feature easily allows you to copy or move a database from one server to another or within one server.

But before you can do this you need to ensure the following conditions:

  • SQL Server Agent service must be running on the destination server
  • SQL Server Integration Services service must be running on the destination server
  • These services must be running with an account that has at least sysdbadmin rights on the target sql server.
  • The source database must not have an owner that is a local account to the source server (e.g. LocalServer1\Tom),
    otherwise the transfer will fail. If it is associated with a local account, change the owner, for instance to sa.

Services

After the prerequisites are confirmed, you can launch the Copy Database wizard. There are currently two ways to copy or move the database:

  1. Use the detach and attach method
  2. Use the SQL Management Object Method

 

Use the SQL Management Object Method

1) is significantly faster but requires a share on the target server and a configured Integration Services Proxy Account on the target server. So the easiest way to copy the source is method 2).

After some view steps in the wizard, you reach the Select Server Objects page where Logins are preselected:

SSO

Copying the Logins is not necassarily required unless you have granted some rights to specific logins, so in some cases you can remove the Logins from the Selected related objects list. in some cases.

 

 

Use the detach and attach method

 

If you decide to use this method to copy or move a database, before you can archive this, you need to create a Credential and a Proxy for the SSIS Package Execution in the SQL Server Agent:

To create a credential that will be later associated to the proxy open Server/Security/Credential and right click to open the popup menu where you select New Credential:

NewCredential

The New Credential Dialog is self explanatory so just configure the required values.

Now you can create a  Proxy:

 

Proxy

In the dialog select a proxy name of your choice and as Credential name select the previously created credential. Select at least “SQL Server Integration Services Package” and that’s it:

ProxyDlg

03 March

Contains with the Entity Framework.

Sometimes you need to get a result set for a field that contains any value from an array.
The default approach in LINQ would be:

from var c in data where array.Contains(c.field) select c;

which creates a T-SQL that looks like that:

select * from data where data.field in (1,2,3,...)

Unfortunately, this would produce an error with EF, since Contains is currently not implemented with .NET 3.5SP1.

Therefore, we need a workarround that builds an expression that implements an or for each indiviudal value in the array to be compared against the field:

private void button2_Click(object sender, RoutedEventArgs e)
{
    int[] types = new int[] { 1, 2, 3, 10 };
    using (TomsPortal.TomsPortalEntities1 tp = new TomsPortalEntities1())
    {
        var r = from node in tp.Node where node.Taxonomy.Id != 3 where Contains<Node, int>(types) select node;
        r = r.Where(Contains<Node, int>(node => node.Id, types));

        foreach (var o in r)
        {
            Trace.WriteLine(o.Id);
        }
    }
}

static Expression<Func<TElement, bool>> Contains<TElement, TValue>(this Expression<Func<TElement, TValue>> valueSelector, IEnumerable<TValue> values)
{
    if (null == valueSelector) { throw new ArgumentNullException("valueSelector"); }
    if (null == values) { throw new ArgumentNullException("values"); }
    if (!values.Any()) return e => false;

    var
equals = from value in values
        select
            System.Linq.Expressions.Expression.Equal(
                valueSelector.Body,
                System.Linq.Expressions.
Expression.Constant(value, typeof(TValue))
            );

    var
body = equals.Aggregate((accumulate, equal) =>
        System.Linq.Expressions.Expression.Or(accumulate, equal));

    ParameterExpression
p = valueSelector.Parameters.Single();
    var ex = System.Linq.Expressions.Expression.Lambda<Func<TElement, bool>>(body, p);
   
    return
ex;
}

Intersection with Linq2SQL

 
Imagine you have a data table that is specified as followed:
 
 
CREATE TABLE MyTable
  ArticleId int NOT NULL,
  CategoryId int NOT NULL
 
 
and you want to return all article ids that interesect with an array of Category Id's using LINQ2SQL.
 
Here is a solution:
 
int[] categoryIds = new int[] {29,5201,4};
IQueryable<ObjectNodeView> result = context.MyTable;

// make a select for the first category:
int firstCategory = categoryIds.First();
result = from a in result where a.CategoryId == firstCategory select a;

// now intersect all other categories using a inner join:
foreach(int categoryId in categoryIds.Skip(1))
{
   result = from a in result
      join a2 in context.MyTable on a.ArticleId equals a2.ArticleId 
     where a2.CategoryId == categoryId
     select a;
}
02 March

Urban legends - Truth or Myth?

 

Select with EF is always slower than with Linq2SQL

This is only true when you leave the default value of ObjectQuery.MergeOption or set it to any other value but MergeOption.NoTracking. However, if you do set this value to MergeOption.NoTracking, a select will be 3 times faster than with LINQ2SQL.

The following table compares various scenarios:

Method

Duration (ms)

DataReader

580

DataTable/DataAdapter

2050

Linq2SQL with Tracking

3330

Linq2SQL without Tracking

2550

EDM with MergeOption != NoTracking

4600

EDM with MergeOption = NoTracking

1150

So what you see here is that EDM is the fastest access after DataReader, but also the slowest if tracking is (by default) enabled. Depending on what you do, you might consider to disable Tracking for faster read access, but with the possibility of redundant data in memory.

 

Linq2Sql supports MS SQL only

This is not really true! Though there is currently only one IQueryProvider for MS SQL, but who prevents other SQL Provider to implement their own IQueryProvider? For instance, Oracle offers native DbConnection, DbCommand and DbReader, why not a QueryProvider?

 
 
EDM does not support UDF (User defined Functions)

Unfortunately, as with .NET 3.5 SP1 this is true. Though you can currently describe a function with

<Function Name="MyUDF" Aggregate="false" BuiltIn="false" NiladicFunction="false" IsComposable="true" ParameterTypeSemantics="AllowImplicitConversion" Schema="dbo" ReturnType="nvarchar(max)">

<Parameter Name="title" Type="nvarchar(max)" Mode="In" />

</Function>

where it differs from a stored procedure by IsComposable set to true instead of false, there is currently no support for it. Usage of UDF with EF is announced to be available with .NET 4.0

 
 
Linq2SQL can do everything that EF can do and more

No. There are some features that is currently not possible with EF, but there are also features in EF that is not available with Linq2SQL.

  • EF is significantly (>300%) faster in writing and updating data back to the database
  • EF supports n:m relations which Linq2SQL doesn't
  • Linq2SQL supports contains in query, while EF (currently) doesn't
  • Linq2SQL supports UDF, EF doesn't (with Framework 3.5SP1)
03 February

WPF AttachedProperties

An AttachedProperty is similar to a DependencyProperty, except that the owner of the value is not the UIElement itself but an external UIElement. For instance, the Canvas.Left and Canvas.Top are AttachedProperties.
 
 
In Xaml, you usually assign an AttachedProperty the following way:

<Button Canvas.Left="12" Canvas.Top="44">ButtonText<Button>

 
Now if you want to create an own AttachedProperty, you simply use the propdp code snippet to create a DependencyProperty first:

public int Order
{
     get { return (int)GetValue(OrderProperty); }
    set { SetValue(OrderProperty, value); }
}

// Using a DependencyProperty as the backing store for Order. This enables animation, styling, binding, etc...
public static readonly DependencyProperty OrderProperty =
    DependencyProperty.Register("Order", typeof(int), typeof(MyContainer), new UIPropertyMetadata(0));

 
To change the DependencyProperty to an AttachedProperty, simply replace DependencyProperty.Register to DependencyProperty.RegisterAttached.
 
But if you try to attach this Property to a control, it doesn't work!
You need to Add static Getters and Setters instead of the local "Offset properties in the following way:

public static int GetOrder(UIElement e)
{
    if (e == null) throw new ArgumentNullException("e");
    return (int)e.GetValue(OrderProperty);
}

public static void SetOrder(UIElement e, int value)
{
    if (e == null) throw new ArgumentNullException("e");
    e.SetValue(OrderProperty, value);
}
 
 
And finally, you have created an AttachedProperty you can use with other Controls.
 
Here is the complete code:

[

ContentProperty("Items")]
public class MyContainer : ItemsControl
{
    static MyContainer()
    {
        DefaultStyleKeyProperty.OverrideMetadata(
typeof(MyContainer), new FrameworkPropertyMetadata(typeof(MyContainer)));
    }

    public static int GetOrder(UIElement e)
    {
        if (e == null) throw new ArgumentNullException("e");
       
return (int)e.GetValue(OrderProperty);
    }

    public static void SetOrder(UIElement e, int value)
    {
        if (e == null) throw new ArgumentNullException("e");
        e.SetValue(OrderProperty, value);
    }

    // Using a DependencyProperty as the backing store for Order. This enables animation, styling, binding, etc...
   
public static readonly DependencyProperty OrderProperty =
        DependencyProperty.RegisterAttached("Order", typeof(int), typeof(MyContainer), new FrameworkPropertyMetadata((int)0));
    }

 

Now you can use it the following way:

<

Window x:Class="AttachedProp.Window1"
    xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation
    xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml
    xmlns:m="clr-namespace:AttachedProp"
   
Title="Window1" Height="300" Width="300">
   
<Grid>
        <m:MyContainer>
            <Button Canvas.Bottom="3" m:MyContainer.Order="3">OK</Button>
       
</m:MyContainer>
    </Grid>
</
Window>

 

Now if you want to use the AttachedProperty within  a ControlTemplate you cannot simply use TemplateBinding. The following snippet shows the correct syntax.

 

<Style TargetType="{x:Type local:MyControl}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:MyControl}">
                <Border Background="{TemplateBinding Background}" Height="40"
                             BorderBrush="{TemplateBinding BorderBrush}"
                             BorderThickness="{TemplateBinding BorderThickness}">
                      <TextBlock Text="{Binding Path=(local:MyContainer.Order), RelativeSource={RelativeSource TemplatedParent}}" />
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Notice the surrounding bracket on the Path property which is mandantary as well as the appearance of Path. Thus you cannot use the following shortcut:

<

TextBlock Text="{Binding local:MyContainer.Order RelativeSource={RelativeSource TemplatedParent}}" Background="Red" MinHeight="24" />

02 December

Symmetric Encryption with windows mobile

 
The .NET Framework offers a lot of different symmetric and asymetric encryption algorithm, as well as the compact framework for window mobile. But one important class is missing in the compact framework:

Rfc2898DeriveBytes

This class provides functionality to create key data from an arbitary password string, which is required for every encryption algorithm. You cannot simply convert the password string to a byte[] array using e.g. Encoding.Default.ToArray(password), since the key must  be of a specific size. The size can vary by different blocks and it depends on the algorithm you are using. For instance, the prefered AES or Rijndael algorithm requires a key size of 128, 256, 384, etc. but nothing between. Therefore you need an algorithm that encodes any string to a byte array of at least 128 bytes and not less or more.

Fortunately, this is what hashing algorithm's do! So as a replacement for the missing Rfc2898DeriveBytes, we can use a has algorithm, that belongs to the compact framework, and that creates a size that matches the requirements for the encryption algorithm. In this case, since we are  using AES, we need a hash with a size of 128 or 256, and the qualified match is the MD5 algorithm. It is not the strongest though, and SH256 would be the better choice, but unfortunately, the compact framework does not include this hash algorithm, so we need to use MD5.

 Here comes an example of how to implement encryption/decryption for windows mobile:

/// <summary>
/// Encrypts a string using symmetric encryption.
/// </summary>
/// <param name="message">The message string to be encrypted.</param>
/// <param name="password">The password for encryption.</param>
/// <returns>A byte array with the encrypted message.</returns>
public byte[] EncryptSymmetric(string message, string password)
{
   // RijndaelManages is the prefered symmetric algorithm, since it has the strongest encryption and it is completely managed code:
   SymmetricAlgorithm sa = new RijndaelManaged();
  
   // apply key and IV to the algorithm, depending on password:
   PasswordToKey(password, sa);
  
   byte
[] binary = Encoding.Unicode.GetBytes(message);
   MemoryStream ms = new MemoryStream();
   CryptoStream stream = new CryptoStream(ms, sa.CreateEncryptor(), CryptoStreamMode.Write);
   stream.Write(binary, 0, binary.Length);
   stream.FlushFinalBlock();
   stream.Close();
   byte[] encrypted = ms.ToArray();
  
   return
encrypted;
}

/// <summary>
/// Decrypts a byte array to a string, using symmetric encryption.
/// </summary>
/// <param name="encrypted">The encrypted data as byte array.</param>
/// <param name="password">The password for decryption.</param>
/// <returns>A string with the decrypted message.</returns>
public string DecryptSymmetric(byte[] encrypted, string password)
{
   // RijndaelManages is the prefered symmetric algorithm, since it has the strongest encryption and it is completely managed code:
   SymmetricAlgorithm sa = new RijndaelManaged();

   // apply key and IV to the algorithm, depending on password:
   PasswordToKey(password, sa);
   using (MemoryStream ms = new MemoryStream())
   {
      using (CryptoStream stream = new CryptoStream(ms, sa.CreateDecryptor(), CryptoStreamMode.Write))
      {
         stream.Write(encrypted, 0, encrypted.Length);
         stream.Flush();
         stream.Close();
      }
      byte[] decrypted = ms.ToArray();
      string s = Encoding.Unicode.GetString(decrypted);
      return s;
   }
}


/// <summary>
/// Generates key and IV from the specified password, using an MD5 hash.
/// </summary>
/// <remarks>
/// Usually you would prefer to use Rfc2898DeriveBytes for this purpose but since
/// .net compact framework (for windows mobile) does not have any implementation
/// for Rcf2898DeriveBytes or even PasswordDeriveBytes, this is a simple workaround
/// for it.
/// </remarks>
/// <param name="password">The password to generate a key/ITfrom it.</param>
/// <param name="sa">The SymmetricAlgorithm class for which to create a key/IV pair.</param>
private static void PasswordToKey(string password, SymmetricAlgorithm sa)
{
   HashAlgorithm hashAlgo = new MD5CryptoServiceProvider();
   byte[] hash = hashAlgo.ComputeHash(Encoding.UTF8.GetBytes(password));
   sa.BlockSize = hash.Length * 8;
   sa.Key = hash;
   sa.IV = hash;
}


private void button1_Click(object sender, EventArgs e)
{
   string message = "This is the message to be encrypted";
   string password = p@ssw0rD;

   byte
[] encrypted = EncryptSymmetric(message, password);
   string decrypted = DecryptSymmetric(encrypted, password);

   MessageBox.Show(decrypted);
}
 

 

 

08 September

WPF BreadcrumbBar

A windows vista like breadcrumb bar for wpf that supports any kind of hierarchical datasource, HierarchicalDataTemplate, dynamic population, command buttons, dropdown list, a progressbar inside and many more.
 
The BreadcrumbBar is part of the new Odyssey assembly that I'm currently developing which will contain various neat controls, introducing the breadcrumb bar.
 
You're welcome to use the BreadcrumbBar for your own applications without paying any charge. The source code with two example appications is available on popfly:
 
 
The included examples show how to populate the breadcrumb bar on demand and conversion from edit path to display path and vice versa by implementing a folder browser, the other examples shows how to use the breadcrumb bar with an XmlDataSource without writing any custom code.
 
Feel free to use it!
 
 
 
18 December

70-528 and 70-529 exams passed

Meanwhile, I also got the other 2 MCTS certificates for Web und Distributed Applications. Both of them, I passed with a score of 1000, or in other words by 100%. Although this sounds like it is easy to make a microsoft exam, the opposite is true. The questions are quity difficult and without training it's hard to figure out the right answer. But with sufficient training, you don't even need to read the complete text for a question. Sometimes it's sufficient to only take a peek to the possible anwers to figure out which of them is the correct one. For some questions, you need to seek for keywords only to filter out the possible answer. You even shouldn't read the question to precisely as this would lead to the decission that there is actually no correct answer. In other words, you need to get a feeling what the questions is supposed to be for. Honestly, even at my latest training tests, I didn't ever archive a score of 1000. Maybe I was a little bit to fast or not to much concentrated as on my real exam.
 
My next exam is the 70-549 to become a Microsoft Certified Professional Developer, and although I haven't even read the MCPD book for 549, I would be able to pass a exam. I made to 2 exams and my quote was already over 75%. The MCPD is more about logic than about details. But for some questions it's better to know the details, which caused me to choose the false anwers for the other 25%. But my goal is to also pass the 549, the 547 and 548 exams with also a score of 1000 points.
 
27 November

70-526 exam passed

Last monday, one week after passing the 70-536, I also passed the 70-526 exam which in my opinion was far easier than the 70-536, except the setup and deployment stuff, where i got only 40% correct answers. anyway, at the other 6 categories I made only one false answer and I don't care about memorizing the exact name of the dialog, treeview, tab page and button i need to click to configure anything. If I need it, I'll find it.
 
I had only one week of preparation, while also still working. But it was easy for me as windows and component development is my big domain, where I'm most experienced (except setup and deployment) so I didn't have much to memorize for preparation.
I also discovered, that there have been questions about classes that weren't part of the ms self paced training book. For instance the TransactionScope class that I had to handle with on several questions, but didn't read anything about it in the book.
 
No that have all required exams, I'm a MCTS for windows applications and currently prepairing for my next exam, the 70-528 (web applications) and finally the 70-529 (web services) that I'm anxious to pass both this year. Then, january 2008 I will complete my exams by passing the 70-549 to finally be granted to the most valuable MCPD of enterprise architect and make some additional MSSQL and Sharpoint MCTS afterwards....
19 November

How to make a Microsoft Certificate

Almost one year ago, I decided to make all the necessary certificates to become a MCPD, a Microsoft Certified Professional Developer. This title sound like a very big honor, and indeed it is. Passing a Microsoft Certificate is not as easy as I assumed, and this is my story:

 

For .NET 2.0, Microsoft offers multiple grades of certificates. You need to pass 2 exams to become either a web, windows or distributed application MCTS (Microsoft certified technology specialist). All of them have the 70-536 exam in common, which in my opinion is the most difficult of them. In addition, for each of these 3 certificates you can upgrade to become a MCPD by passing one additional exam which differs for each category with one exception: for the 70-549 exam that grades you the rank of a Microsoft certified professional Developr for Enterprise Applications, you need to pass all previous MCTS certificates and this is what I'm longing for.

There are different ways to pass these exams. You can join a 2 week training course, which is about $5000, or you can simply buy the required books and make a self paced training. The books include a training software from measureup to test your knowledge. But you'd better don't rely on the knowledge you'll receive by making all 300 tests again and again and again until you memorize them. Because the real exam tests are completely different! You really need to know the issues that are included in the exam category to pass them.

It took me 3 weeks to read and prepare for the 70-536 exam, the "Application Development Foundation" which I mentioned earlier. I was also grabbing for some reports of other graduates who made this exam to figure out how exactly it works and how difficult it is. When I'd read that the real exam is supposed to be much harder than then the measureup test, I was frightened! Because the measureup test are anything else but easy! Even if you have years of .net experience like me or other developers, the questions are a pain in the ass. But on the other hand, I heard and read that the real tests are easier, they'd be obvious, and so, last week I decided to make my first exam as soon as possible and applied for a test this Monday.

This works as followed:

 

There are many test centers, where you can make a Microsoft exam or other exams. For a Microsoft exam (note: not a complete certificate that consists of multiple exams!) you have to pay €140 for the exam itself and additionally a fee for the test center which is about €20-30. To find a test center near your location, you first need to register at www.prometric.com then you can follow the links to the exam of your choice and select a test center at your location. Sometimes, there are more than one centers for the same city available. Next step, you choose the day of your choice when you want to make the exam (If a test center doesn't offer the date, maybe you can select another one). Finally, you select the time when you want to make the exam,which depends on the selected center. I could choose within 9:00 and 17:00. The duration of a test is scheduled to take 3:15 hours. You also can choose of the either English, French, German, Japanese or Chinese for the exam. (I chose English as my Japanese needs a little improvement).

After you have selected you're appointment, you'll receive an e-mail confirmation.

 

I chose Monday because it gives me a complete weekend to prepare for it. Against all odds, I was neither tensed nor I was nervous and on Sunday, I slept very well. I still was relaxed when I arrived at the test center:

So there I was, to match me intellect, to become one of the most important people of the universe.
After filing in at the reception, I had to authenticate myself with an certified document including a pass photo (usually your identity card). You can't take any book, computer, notebook, pda or cell phone to the test. If you keep one of these with you, you'll need to hand out them. Next step, guarding you to a prepared room with computers and surveillance where you'll gonna spend the next 3 hours (or maybe less) of your life. Three hours, that will change your life forever!

I still wasn't tensed or nervous when I was introduced to my computer, handing out an empty peace of paper and a pen for notes that I could make (but I was not in the mood of making any kind of notes or drawings or anything like that). Before the exam starts, you'll click trough some informations about the test and the conditions. For instance, it's not allowed to make any photos or copies of the text, or to spread them on the internet or stuff like this. You got 60 minutes or so for that, and when you feel ready, when you're of the opinion that you will make it, that the sake of the whole universe is in your hand, then you can press the final button and the exam begins. Now you have 120 minutes for 45 questions. You need to get a score of 700 of 1000, so you need to pass only 70%. But the catch is, that each question is weighted differently, so it doesn't mean that you need to have 31.5 correct questions.

 

After seeing the first question, I was totally calm. The question was not that difficult, so I experienced the next 4 questions. Now I was tensed! And I was nerveous! I was wondering where that steady knocking came from and I figured out that it was my heard beating! These questions have been totally knew to me and in no test that I made for preps earlier, I've seen anything similar like this! I was wondering If I do understand the question. What does it mean, what do they want from me? Why can't they leave me alone? until question 31, I was alone in the room when another candidate was introduced to that room on another computer. I heared every click he made with the mouse and it was sooo distracting. I couldn't concentrate, I was counting the pauses between a click and was wondering why he was clicking so fast! Propably another test, as my test was a lot of stuff to read and to scroll down to find a difference between answer a,b,c or d.  Anyway, I could not concentrate on the test as long as he keeps klicking all the time like a maniac!

Finally, after question 45, the last one, I had almost one hour left so I checked each question again. 10 minutes left I thought that I couldn't do more for me and the whole mankind. So I clicked the "finish" button. I was a little bit scared as the screen became white for a couple of minutes. What If all my answers are lost? What I this means I would not pass my exam?

But then there as a screen again. But it was not the result of my test! No, I now have the chance to leave comments for each question. I wanted to make some comments to some of the question where it seamed clear to select the correct answer, but I didn't find them spontaneously and I was too curious if I will have passed the exam, so I clicked finished again.

 

And finally, there it was, the answer of all questions, The salavation of the lost. The truth!

And the answer was "Congratulation, you passed your exam".

I was hand out a document, with the detailed result for all 7 categories of my test (but not the each question) and then I was free to go. To continue my journey on the way to become a respected MCPD.

 

 

28 July

Performance of LINQ

Curious of how fast LINQ would be to filter items from a large list, I was writing a test In Visual Studio 2008 Beta 2 to determine the performance, by creating a List of a class that contains 1 million items to be filtered and sorted:

        
        // Performing a LINQ command for a list of 100.000 items:
        public IEnumerable<item> Filter(IList<item> list) 
        { 
            IEnumerable<item> items =
                from it
in list where it.value < 40 || it.text.StartsWith("W")
                orderby it.text select it; 

            return items; 
        } 

                // Create a list of 1,000,000 items with random value:    
        private void button2_Click(object sender, RoutedEventArgs e) 
        { 
            List<item> items = new List<item>(); 
            Random r = new Random(); 
            Random m =new Random(); 
           
for (int i = 0; i < 1000000; i++) 
            { 
                StringBuilder sb  = new StringBuilder(); 
                for (int x=0;x<10;x++) 
                { 
    
                    char c = (char)(m.Next(27)+65); 
                    sb.Append(c); 
                } 
                item item = new item(); 
                item.text = sb.ToString(); 
                item.value = r.Next(100000); 
                items.Add(item); 
            } 
   
            int t1 = Environment.TickCount; 
    
            IEnumerable<item> filtered = Filter(items); 
    
    
            bool stopped = false;
            foreach
(item it in filtered) 
            { 
              if (!stopped)
              {
                int t2 = Environment.TickCount; 
                Trace.Write("Duration: "); 
                Trace.WriteLine(t2 - t1);
                stopped = true;
              }

                Trace.Write(it.value); 
                Trace.Write(" "); 
                Trace.WriteLine(it.text); 
            } 
    
        } 
    } 
    
    public class item 
    { 
        public int value; 
        public string text; 
    } 
 

To filter 1,000,000 items, it took only 631ms on a @2400GHz Core 2 Duo that was even virtualized with Virtual PC!
That's very impressive!


Note, that the LINQ result IEnumerable<item> does NOT immediately perform to filter but after the first item is request, so that explains the weired code and why I was using the stopped variable.

 

01 July

Apple Safari on Vista

 

Today I was testing a more or less stable version of apple's safari browser. First I was eagerly trying out the rss feed functionality, and I discovered that safari does indeed support rss feed in a way that makes rss reasonable. This is a big advance in contrast to firefox. even 3.0 of firefox does not really support rss, although it claims to, it's just a useless menu point, whereas safari offers fully support like IE7 does, although IE7 is still a more nifty. Unfortunately safari lacks on websites with various rss feeds. Against IE7 that show all of then in a drop down menu, safari only offers the first grabbable rss feed.

Also a very nice feature (but more for the fun factor and not really necassary) is the nice animation, safari provides on moving a tab or layouting the toolbar buttons. In short words, it simulates an animation that vista's sidebar does, but anyway, would be a nice feature for the wow effect on IE8.

Disappointing is the search bar. as default there is google selected and you can only select yahoo but there is currently no way to use live as seach engine. so this makes actually the search bar useless. or is there really someone out there who still uses google? my recommendation to apple is not only to offer live as seach engine but also set it as the default.

Also impressive is the inline search. Against IE7, that opens a separate window for input, the safari show's a separate toolbar as soon as you press Ctrl+F and higlights a match instantly while typing the text. Both methods have their pro's and contras, and none of theme have a better usability.

But there's at least one thing that is really better than IE7: The integrated download manager. I hope that IE8 will offer this very usefull functionality, but I fear that Microsoft might get problems integrating this functionality by third party's, like always.

The global usability is not as comfortable as IE7, but it can easily compare with firefox.

So my conclusion is, that safari will become a serious threat to firefox, so at the end firefox might loose popularity. For IE7 i see no serious challenge.

20 April

Partial classes

Partial classes is a nice feature coming with .NET 2.0. With partial classes, it is possible to split one bigger class into separate files. For instance, Visual Studio 2005 automatically separates the business and design logic of a control class into to files: filename.cs and filename.designer.cs.

For some purposes it could be very neat to separate parts of a class that belong to a group of functionality into some more files. To do this, you simply need to create a new file, name it ClassName.addition.cs. Visual Studio 2005 treats all file names before the first point as one, so you only need to define in both files the class with the partial keyword e.g.:

 

public partial class MyClass

{

}

 

As I mentioned, it really makes sense, for instance, I got a form that has an edit and a display mode, so I separated the business logic of these modes into separate files, so I don't lose track of it.

 

17 April

Vista Complete PC Restore

Note: The vista complete pc restore is a functionality which is present on windows vista ultimate and windows vista business but not home premium or home basic

Today, when I came home from work, I had a unpleasant surprise when I was synchronizing my laptop with my pc:
At the tray, I noticed a new tray icon, so I clicked on it to find out what it is for. It opened a dialog that informed me that my Intel Raid 0 with 2 hd has detected an error on one disk and I should perform a complete backup asap. I'm using 2x250 hds and although I got a usb hd for backup purpose, this backup disk would never fit the required size. So I removed all temporary files and deleted all restore points except the latest to make size. From 260 gb of used bytes I could shrink it to 180 gb! Nice work, but still to much for my 80 gb backup drive. So I decided to abuse my windows xp computer with a 2x80 raid 0 system which I only use occasionally for windows xp testings and plugged them onto my vista computer and made my first complete backup. Other than a standard backup, the complete backup does not compress the files, so the size is indeed the same as the hd requires. It creates a *.vhd file that possibly can be used on a virtual machine like virtual pc 2007.

Now I could spend my time to attempt to solve the disk problem. What I did was simply delete the raid and recreate it again. Unfortunately, this also caused the contents of the raid getting lost, but no problem I got a backup! I restarted my pc with my windows vista ultimate dvd and instead of installing I selected the restore option, loaded the drivers for the backup raid (which was not an intel driver) from a usb stick that I've loaded from the internet with my laptop, and it detected the backup. Currently the computer is still restoring.

Finally, I got to say that this functionality is a very nice feature, because it saved me lots of time reinstalling vista and all applications again, which would take at least one day, maybe too.

16 April

Sliverlight

Microsoft Silverlight is a new cross platform multimedia streaming client that will make the adobe flash player obsolete.

You can get more details about silverlight at the following web site:

 

http://www.microsoft.com/silverlight/default_01.aspx

14 April

Code snippet

Here is a code example for an application that converts toolbar images by size and compression. I pulish this application for the sake of offering hints and ideas of how to develop software with .NET 2.0.
 
Interesting might be the IsImage() method where I check if a file name has an extension of an image. Instead of checking each possible extension separately I use a loop and a string[] collection that is initialized staticly which makes this method easy to read, small in code and easily to extend.
 
Also interesting might be how to implement drag & drop functionality to an application and read the items that where dropped on it, eq. from the windows explorer.
 
Now here comes the code:
 

SourceImage.cs

 

namespace ImageConverter
{     public class SourceImage
    { 
        public SourceImage(string path) 
            : base() 
        { 
            this.path = path; 
        } 
  
        internal string path; 
  
        public string Path { get { return path; } } 
        public string Name 
        { 
            get 
            { 
                return System.IO.Path.GetFileNameWithoutExtension(path); 
            } 
        } 
  
        internal string RenameExt(string extension) 
        { 
            string ext = System.IO.Path.GetExtension(this.path); 
            string name = Name;
             { 
                name = name + "_copy"
            } 
  
            string path = System.IO.Path.GetDirectoryName(this.path); 
            path = System.IO.Path.Combine(path, name) + extension; 
            return path; 
        } 
    }

  
    public class SourceImageList : List<SourceImage
    { 
        public SourceImage Add(string path) 
        { 
            SourceImage image = new SourceImage(path); 
            Add(image); 
            return image; 
        } 
    }
 

ImageFormats.cs

 

namespace ImageConverter

    public sealed class ImageFormatInfo 
    { 
        public ImageFormatInfo(ImageFormat format, string extension, string description) 
            : base() 
        { 
            this.format = format; 
            this.description = description; 
            this.extension = extension; 
        } 
  
        private string extension; 
        private string description; 
        private ImageFormat format; 
  
        public string Extension { get { return extension; } } 
        public string Description { get { return description; } } 
        public ImageFormat Format { get { return format; } } 
    } 
  
    public sealed class ImageFormatList : List<ImageFormatInfo
    { 
        public ImageFormatList() 
            : base() 
        { 
            Add(ImageFormat.Bmp, ".bmp", "Bitmap"); 
            Add(ImageFormat.Jpeg, ".jpg", "Jpeg"); 
            Add(ImageFormat.Gif, ".gif", "Gif"); 
            Add(ImageFormat.Png, ".png", "Png"); 
        } 
  
        private void Add(ImageFormat format, string extension, string description) 
        { 
            Add(new ImageFormatInfo(format, extension, description)); 
        } 
    }
}

 

Form1.cs:

 

namespace ImageConverter

    { 
        Size imageSize = new Size(16, 16); 
        private Color imageBackground = Color.Fuchsia; 
  
        public Form1() 
        { 
            InitializeComponent(); 
            ImageBackGround = Color.Fuchsia; 
            cbTarget.DataSource = formats; 
        } 
  
        private ImageFormatList formats = new ImageFormatList(); 
        private SourceImageList sources = new SourceImageList(); 
  
        public Color ImageBackGround 
        { 
            get { return imageBackground; } 
            set 
            { 
                imageBackground = value
                tbColor.BackColor = value
            } 
        } 
  
        private void listView1_DragOver(object sender, DragEventArgs e) 
        { 
            e.Effect = e.AllowedEffect; 
        } 
  
        private void imageList_DragDrop(object sender, DragEventArgs e) 
        { 
            string[] images = (string[])e.Data.GetData(DataFormats.FileDrop, false); 
            foreach (string image in images) 
            { 
                if (IsImage(image)) 
                { 
                    SourceImage sourceImage = sources.Add(image); 
                    if (image!=null
                    { 
                        imageList.Items.Add(sourceImage.Name).Tag = sourceImage; 
                    } 
                } 
            } 
        } 
  
        private bool IsImage(string image) 
        { 
            string ext = System.IO.Path.GetExtension(image); 
            string[] extensions = { ".bmp", ".gif", ".jpg", ".jpeg", ".png" }; 
            foreach (string extension in extensions) 
            { 
                if (ext.Equals(extension, StringComparison.OrdinalIgnoreCase)) return true
            } 
            return false
        } 
  
        private void btConvert_Click(object sender, EventArgs e) 
        { 
            ImageFormatInfo format = cbTarget.SelectedItem as ImageFormatInfo
            foreach (SourceImage image in sources) 
            { 
                using (Bitmap targetBm = new Bitmap(imageSize.Width, imageSize.Height)) 
                { 
                    Graphics g = Graphics.FromImage(targetBm); 
                    g.Clear(imageBackground); 
                    using (Bitmap sourceBm = new Bitmap(image.Path)) 
                    { 
                        sourceBm.MakeTransparent(); 
                        int x = (imageSize.Width-sourceBm.Width)/2; 
                        int y = (imageSize.Height-sourceBm.Height)/2; 
                        g.DrawImageUnscaled(sourceBm, x, y); 
  
                        string fileName = image.RenameExt(format.Extension); 
                        targetBm.MakeTransparent(ImageBackGround); 
                        targetBm.Save(fileName, format.Format); 
                    } 
                } 
            } 
        } 
  
        private void button1_Click(object sender, EventArgs e) 
        { 
            colorDialog.Color = ImageBackGround; 
            if (colorDialog.ShowDialog() == DialogResult.OK) 
            { 
                ImageBackGround = colorDialog.Color; 
            } 
        } 
  
        private void btClear_Click(object sender, EventArgs e) 
        { 
            sources.Clear(); 
            imageList.Clear(); 
        } 
  
        private void numericUpDown1_ValueChanged(object sender, EventArgs e) 
        { 
            imageSize.Width = (int)((NumericUpDown)sender).Value; 
        } 
  
        private void numericUpDown2_ValueChanged(object sender, EventArgs e) 
        { 
            imageSize.Height = (int)((NumericUpDown)sender).Value; 
        } 
    }
}
 

 
 
 
13 April

The Breadcrumb Bar

Since Windows Vista, you're familiar with this new kind of control. The breadcrumb bar was introduced with the windows explorer and replaces the combo box for the path. But the breadcrumb offers much more than only showing the path. It separates each sub folder as a breadcrumb so the user can go back with ease by just clicking the appropriate breadcrumb or selects another sibling of a breadcrumb which represents another folder inside a folder. The breadcrumb bar can also include some image buttons on the right and an icon on the left as well as a dropdown button that behaves like the dropdown button of a combo box. Even a progress bar is included in the breadcrumb bar!

You can use a breadcrumb bar not only for paths but also for other purposes. For instance in my profession I'm developing an application that shows the medical history of a patient. In the breadcrumb bar, I offer the name of the patient and also the available health insurance voucher of the patient, followed by its type, and the date separated by year, quarter or month, day that may look like this:

Miller, Max (2003-03-24) à Emergency à AOK Berlin à 2007 à November à 15

This is just one other example for what a breadcrumb bar can be used for, there are so many other possibilities. As I'm developing .NET applications, I wrote a breadcrumb bar as part of my jedi.dll assembly which also contains the previously mentioned JediGrid. Soon the jedi.dll will be available for free private use on www.tomssoftware.net, just be patient.

Here is a brief scheme of the breadcrumb bar:

11 April

Using BinarySearch to find lower or higher values

.NET 2.0 offers an easy way to find any item of a generic list that is sorted by the item to get using a binary search that has an order of O(ln N). But what if you need to find an item that has not the exact value and you want to find the item that is lower/equal or higher/equal? Fortunately, the BinarySearch method also supports this situation:

 

BinarySearch returns the item index that matches the item to find, otherwise the return value is less than zero. But this value is a negative value that represents the nearest item that is lower than the item to search minus 2.

 

The following example uses this feature to find an item that is either equal or less than the index to search for:

 

First, a comparer class is derived that compares the items. The constructor has a parameter for the index to find instead of specifying a class for the BinarySearch method. As the BinarySearch will be parameter less, the second parameter for the Compare method will always be null and can be ignored:

 


        /// <summary>
        /// A comparer class to compare the groups list to find a item faster using binary search.
        /// </summary>
        class MyComparer : IComparer<MyClass>:IDisposable
        {
           
public MyComparer(int index)
                :
base()
            {
               
this.index = index;
            }
          
private int index;
 
           
public int Compare(MyClass x, MyClass y)
            {
               
return x.index - index;
            }
         }

 

The following method LowerOrEqualValue finally performs the search by creating a MyComparer class. If the result value of BinarySearch is positive or null, an item with exact the required index exists, otherwise the index is a negative value of the nearest index that is less than the specified index, so we make it positive with the formula

resultIndex = -2 – resultIndex

Note that, if there is really no item, the return value would be -1 so the formula finally would also be -1.

 
       private int LowerOrEqualValue(int index)
        {
           
using (MyComparer comparer = new MyComparer (index))
            {
               
int resultIndex = items.BinarySearch(null, comparer);
               
if (resultIndex < 0) resultIndex = -2 - resultIndex;
               
if (resultIndex >= 0 && resultIndex < resultIndex.Count)
                {
                   
return resultIndex;
                }
               
return -1;
            }
        }

 

If you don't need the next lower item but the next higher value, you just need to replace the formula by

resultIndex = -1-resultIndex

But then you must explicitly check the situation of no result when BinarySearch returns -1!

 

09 April

Announcement

Soon I will offer a free version of the Jedi Library for download with the following contents:

 

  • JediGrid (an optimized DataGridView with support for groups, treeview and tiles, with the fastest generic auto sorting, up to 10 times faster than other professional data grids)
  • DockPanel (allows to group and nest panels with each other with the possibility to move them on runtime while performing a neat visual animation, introducing the smart placing algorithm)
  • Sidebar (A combination of windows sidebar and outlook sidebar, containing sections and groups)
  • GlossyRenderer (Non visual control, but provides functionality to paint neat backgrounds that are used by all controls of the Jedi library)
  • BreadcrumbBar (An implementation of a breadcrumb bar as you know from window vista's explorer).

     

The library will be free of charge for private use though it is not allowed to use it for professional applications without permission!

Distribute assemblies with documentation

XML Documentation on VisualStudio 2005 is a very neat thing that offers online help of the classes and its members without the need of opening the source file. But as soon as you distribute an assembly without source code, the documentation is not available when you use a class of the assembly by default. To have the documentation available that you (hopefully) created, you need to add an xml file the contains the documentation. Fortunately, to create this xml file is a piece of cake as Visual Studio 2005 does it for you. You simply need to do the following steps to enable xml documentation:

 

  • Open the project properties
  • At the Build page ensure XML Documentation file is checked:

 

  • Finally simply recompile your project. But if you not have already documented all public and protected methods and classes, you will get additional warnings for those methods and classes. It's a little bit annoying to document every method even commonly known derived methods like OnPaint, but some tools like GhostDoc help to minimize the steps.

 

 

06 April

JediGrid

The JediPanel is part of the new Jedi assembly that I'm creating including various controls such as
 
  • JediGrid
  • DockPanel
  • GlossyRenderer
  • Sidebar
  • BreadcrumbBar

for for details about the JediGrid see the PowerPoint presentation:

http://www.msnusers.com/n17u6qt1kivpohh9q0l6njksc1/Documents/JediPanel2.pptx

01 April

Does Ready Boost slow down your system?

There are certain rumors about this issue that claim that as soon as ready boost is installed, the cpu raises from 1% idle time to constantly 30-40%, like the following article:
 
 
  • how serious are these reports?
  • what is fact?

The truth is, the reports a right, but:

  • as soon as you install a new medium for ready boost, vista analyzes the system to determine what can be extended to the external medium. This analysis requires a view minutes and does indeed consume resources so that your computer can become unhandsome.
  • Also, when you reboot, this anayzing process starts when you log in, but
  • Vista is designed not to shut dow when you press the exit button, but rather going in standbye or sleep mode due to the fact that meanwhile all main boards and cards supports standbye and against common opinion that standbye consumes more power thant to shut down the computer, the truth is, that there is not difference in power consumption whether you are in sleep mode or you have indeed shut down your computer. Only when you switch the button on the back of your computer, it is really off.

 

So I come to the result, that ready boost does what it's supposed to do, to increase the performance of your computer as long as you use you're vista computer like it was designed to be used.

Rumors that claim to say the oposite are either mistaken because of the analyzis process, or just propaganda from tux landers.

 

 

01 March

How refactoring can improve the comprehensibility of source code.

These examples show two kinds of the same code that speak for itself:

 

Figure 1

  static class Program 
  { 
    public static string[] Args = null
       /// <summary> 
    /// The main entry point for the application. 
    /// </summary> 
    [STAThread
    static void Main(string[] args) 
    { 
      if (Properties.Settings.Default.DebugLog) 
      { 
        /// Copy all Trace and Debug reports to columnAttrib file: 
        /// 
        string file = Properties.Settings.Default.DebugFile; 
        FileStream stream = new FileStream(file, FileMode.Create); 
        stream.Close(); 
        stream.Dispose();
        TextWriterTraceListener listener = new TextWriterTraceListener(file); 
        Trace.Listeners.Add(listener); 
        Trace.AutoFlush = true
        Debug.Listeners.Add(listener); 
        Debug.AutoFlush = true
      } 
   
      Application.EnableVisualStyles(); 
      Application.SetCompatibleTextRenderingDefault(false); 
   
      foreach (string s in args) 
      { 
        if (s.StartsWith("-locale:", StringComparison.OrdinalIgnoreCase)) 
        { 
          string culture = s.Remove(0, 8); 
          System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(culture); 
        } 
      } 
   
      Args = args; 
      AppLauncher launcher = new AppLauncher(); 
      launcher.Run(args); 
    } 
  }


Figure 2

  static class Program 
  { 
    public static string[] Args = null
   
    /// <summary> 
    /// The main entry point for the application. 
    /// </summary> 
    [STAThread] 
    static void Main(string[] args) 
    { 
      PreprareToLogDebugMessages(); 
   
      Application.EnableVisualStyles(); 
      Application.SetCompatibleTextRenderingDefault(false); 
   
      SetCultureFromParams(args); 
      Args = args; 
      AppLauncher launcher = new AppLauncher(); 
      launcher.Run(args); 
    } 
   
    /// <summary> 
    /// If Specified in the Properites Settings, all Debug and Trace outputs are 
    /// redirected to a file. 
    /// </summary> 
    private static void PreprareToLogDebugMessages() 
    { 
      if (Properties.Settings.Default.DebugLog) 
      { 
        /// Copy all Trace and Debug reports to columnAttrib file: 
        /// 
        string file = Properties.Settings.Default.DebugFile; 
        FileStream stream = new FileStream(file, FileMode.Create); 
        stream.Close(); 
        stream.Dispose();
        TextWriterTraceListener listener = new TextWriterTraceListener(file); 
        Trace.Listeners.Add(listener); 
        Trace.AutoFlush = true
        Debug.Listeners.Add(listener); 
        Debug.AutoFlush = true
      } 
    } 
   
    /// <summary> 
    /// Sets the culture for the application if specified by the args. 
    /// </summary> 
    /// <param name="args"></param> 
    private static void SetCultureFromParams(string[] args) 
    { 
      foreach (string s in args) 
      { 
        if (s.StartsWith("-locale:", StringComparison.OrdinalIgnoreCase)) 
        { 
          string culture = s.Remove(0, 8); 
          System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(culture); 
        } 
      } 
    } 
  } 
 

As you see in these code snippets, figure 1 looks very complicated because it's one long function that do various sub parts.

 

In contrast figure 2, although it contains more individual functions, it's easier to understand the meaning of the code, and as a side effect, as logical function parts are separated to a method, you can create an xml header and describe the functionality of the sub part which can be used later for automatic documentating.

25 January

Encoding and Decoding of code pages

 
Sometimes you'll have to read from a file that has a specific codepage.
Using the FileStream class you can decode the bytes read using the following method:
 

    protected string Read(int size) 
    { 
      byte[] buffer = new byte[size];
      stream.Read(buffer, 0, size); 
      Encoding codepage = Encoding.GetEncoding(437);

      string s;

      if (codepage != null
      { 
        s = codepage.GetString(buffer); 
      } 
      else 
      { 
        s = Encoding.ASCII.GetString(buffer); 
      }

      return s.Trim(); 
    }