Perform LINQ join on nullable and non-nullable types


When working with Nullable types, join statement in LINQ need to be handled carefully. When you perform a join over nullable and non-nullable types,
compile time exception is thrown saying that "Type inference failed in the call to join". For example consider following classes.

public class Employee
{
   public int EmployeeId
   {
      get;
      set;
   }
        
   public string EmployeeName
   {
      get;
      set;
   }
}


public class Employee
{
   public int EmployeeId
   {
      get;
      set;
   }
        
   public string EmployeeName
   {
      get;
      set;
   }
}

To fetch data from these let's write code as;

class Test
   {
       static void Main()
       {
           var employees = new List<Employee>
           {
               new Employee
               {
                   EmployeeId = 1,
                   EmployeeName = "E1",
               },
               new Employee
               {
                   EmployeeId = 2,
                   EmployeeName = "E2",
               },
               new Employee
               {
                   EmployeeId = 3,
                   EmployeeName = "E3",
               },
           };

           var departments = new List<Department>
           {
               new Department
               {
                   EmployeeId = 2,
                   EmployeeName = "E2",
               },
               new Department
               {
                   EmployeeId = null,
                   EmployeeName = "D1",
               },
               new Department
               {
                   EmployeeId = 3,
                   EmployeeName = "E3",
               },
           };

           var r =
               from dept in departments
               where dept.EmployeeId != null
               join emp in employees
               on new { SourceEmployeeID = dept.EmployeeId.Value, SourceEmployeeName = dept.EmployeeName }
               equals new { SourceEmployeeID = emp.EmployeeId, SourceEmployeeName = emp.EmployeeName }
               select new
               {
                   emp,
                   dept,
               };

           foreach (var item in r)
           {
               Console.WriteLine("{0}", item.emp.EmployeeId);
           }
       }
   }
}

The query highlighted in above code will match the LHS with EmployeeID which is nullable with RHS EmployeeID which is not nullable.

Setup your own source control system

How to setup your own SVN system on local machine?

  • Download and install tortoise SVN
  • Create a folder which will be used as a server folder say "F:/ServerData".
  • Right-click to this folder and select "create repository here"
  • This will create a server folder and will provide you the repository path e.g. file:///F:/ServerData
  • Create another folder which will be served as a client folder say "F:/SourceData"
  • Right-click to this newly created folder and select SVN-checkout option
  • Provide repository path obtained in previous step. This will create a repository folder structure with 3 sub-folders as branches, tags and trunk.
  • Now copy the source folder under trunk folder.
  • Right-click trunk , select TortoiseSVN -> Add. This will add your source code under source control.

All set and you are ready to use your own source control system to track your own progress.

How to guarantee memory cleanup using Dispose()


  
It's been said that Dispose() function cleans up the memory utilized by objects. Now consider a scenario where you have created an instance. 


.Net CLR may eventually call its Finalize() method, but Dispose() is never called automatically. Calling Dispose() method is the responsibility of consumer of your instance.

Now let's say you have called Dispose method explicitly. In the flow of execution if any exception is thrown before reaching to the call to Dispose() method, the memory leak can arise.

To resolve this issue C# provides a using keyword. Advantages of making use of using keyword it calls the Dispose() method in finally block. You can verify the code in MSIL.


try
{
}
finally
{
    IL_0010: 1dloc.0
    IL_0011: brfalse.s IL_0019
    IL_0013: ldloc.0
    IL_0014: callvirt instance void [mscorlib]system.IDisposable::dispose()
    IL_0019:endfinally
}

//Test.cs
using System;

namespace DisposePattern
{
    class Test
    {
        [STAThread]
        static void Main(string[] args)
        {
            using(Derived object1 = new Derived(1))
            {
                Derived object2 = new Derived(2);
            }
        }
    }
}

You can declare more than one reference in the using declaration: using(Derived obj1 = new Derived(1), obj2 = new Derived(2)) The Dispose() method, in this case, will be called on each referenced object at the appropriate time. You can also achieve this without making use of using keyword. What you have to do is to call Dispose() in finally block. The using keyword in C# improves your chances of cleaning up your resources properly.

How to create a comma separated string from List

Here is a sample code which shows how to create a comma separated string from List<string>. I know this is not a big deal to do this but in some circumstances it can be used to resolved complex problems.


    List<string> lstStr = new List<string>();
    lstStr.Add("item1");
    lstStr.Add("item2");
    lstStr.Add("item3");
    lstStr.Add("item4");
    lstStr.Add("item5");
    lstStr.Add("item6");

    string str = string.Join(",", lstStr);
    MessageBox.Show(str);

Output of this code will be as;
item1,item2,item3,item4,item5,item6

Now you can manipulate this comma separated string as per your needs.

How to read CDATA section using c#

CDATA means character data is used to store information in markup languages like XML. Here we will take a look at how to read this CDATA section using C#. Let's consider a XML file as;

<?xml version="1.0" encoding="utf-8" ?>
<Books>
  <Book ID="ISBN001" Title="ABC">
    <![CDATA[This is the information of ABC]]>
  </Book >
  <Book  ID="ISBN002" Title="DEF">
    <![CDATA[This is the information of DEF]]>
  </Book >
</Books>

Now we will take a look at the code which will read the CDATA section.

string strPath = @"<<Path of XML file>>";
XmlDocument doc = new XmlDocument();
doc.Load(strPath);
XmlElement root = doc.DocumentElement;
XmlNode node = doc.DocumentElement.SelectSingleNode(
@"/Books/Book");
XmlNode childNode = node.ChildNodes[0];
if (childNode is XmlCDataSection)
{
       XmlCDataSection cdataSection = childNode as XmlCDataSection;
       MessageBox.Show(cdataSection.Value);
}

Here I have retrieved only first node from the xml, you can select nodes as a node list and iterate through it to get CDATA section from all the nodes.

Write text files without Byte Order Mark (BOM)

I was working on a eLearning tool which supports various Learning Management Systems. Out of those one of the LMSs require files written in UTF8 encoding without Byte Order Mark(BOM).

If you are using Notepad++, you will find such type of encoding scheme over there. I was writing this piece of code in VB.Net.

The below code illustrates how to write files omitting BOM.

There seems to be a way of omitting the byte order mark (BOM) via passing False True to the UTF8Encoding constructor (link to MSDN reference page).
That is, use your own instance of UTF8Encoding instead of the default System.Text.Encoding.UTF8:
Dim utf8WithoutBom As New System.Text.UTF8Encoding(True)
                                                  '^^^^'
Using sink As New StreamWriter("Foobar.txt", False, utf8WithoutBom)
    sink.WriteLine("...")
End Using
(Note that omitting the BOM is only permissible for UTF-8, not for UTF-16.)

Datagridview error : Value' should be between 'minimum' and 'maximum'

I was trying to populate data in DataGridView control. It was getting populated into it correctly. But when I was trying to scroll down it was throwing an exception like;

> Value of '352' is not valid for 'Value'. 'Value' should be between
> 'minimum' and 'maximum'. Parameter name: Value

    at System.Windows.Forms.ScrollBar.set_Value(Int32 value)
       at System.Windows.Forms.DataGridView.ScrollRows(Int32 rowCount, Int32 deltaY, ScrollEventType scrollEventType)
       at System.Windows.Forms.DataGridView.ScrollRowsByCount(Int32 rows, ScrollEventType scrollEventType)

The Dynamic binding was used to fill the Datagridview.

After a lot of debugging and searching this issue got resolved with just one statement.
I called dataGridView1.PerformLayout() after populating data.

Thanks to Google :)