Explain about IEnumerable Interface and yield Keyword

Introduction

In this article we will discuss about the IEnumerable interface. We will discuss how IEnumerable interface facilitate the use of foreach statement to iterate through a set of data. We will then look how to implement our own collections that implement IEnumerable interface. The use of yield keyword and Enumerating generic collections will also be discussed in this article.

Background 

Whenever we work with collection of objects, we might find ourselves in need to iterate the collection. The best way to iterate through a collection is by implementing the Iterator pattern. (refer: Understanding and Implementing the Iterator Pattern in C# and C++[^]). C# provides a very clean construct of foreach statement to iterate in a read only manner over a collection.
C# also provides us the possibility of using the same foreach construct and all the enumeration techniques on our custom collection objects by implementing the IEnumerable interface. So let us see how we can implement IEnumerable interface with our custom collection classes.

Using the code

Enumerating the Collection classes

Before starting the discussion let us see how we can use the Built-in classes and iterate over them. Lets start by looking into the ArrayList class that implements IEnumerable and see how we can have read only iteration over that using foreach statement.
// Let us first see how we can enumerate an object implementing IEnumerable
ArrayList list = new ArrayList();

list.Add("1");
list.Add(2);
list.Add("3");
list.Add('4');

foreach (object s in list)
{
    Console.WriteLine(s);
}

Enumerating the Generic Collection classes

The Arraylist class is a generalized class that let us keep a collection. We can also have a generic class in which we can provide the type along with the data. Iterating over generic collection classes is also possible because they implement IEnumerable<T> interface. Lets see how we can enumerate over a generic collection.
// Let us first see how we can enumerate an object implementing IEnumerable<T>
List<string> listOfStrings = new List<string>();

listOfStrings.Add("one");
listOfStrings.Add("two");
listOfStrings.Add("three");
listOfStrings.Add("four");

foreach (string s in listOfStrings)
{
    Console.WriteLine(s);
}
Now our objective is to have our own custom collection class and a generic collection class that should implement the IEnumerable and IEnumerable<T> interface respectively to provide the possibility of enumerating over them.

Understanding the yield keyword

Before jumping into the Implementation of these classes, we need to understand a very important keyword yield which actually facilitate the enumeration over collection. yield statement is used while returning a value from a function.
A normal method call like the one shown below will return only the first value no matter how many times it is called.
static int SimpleReturn()
{
    return 1;
    return 2;
    return 3;
}

static void Main(string[] args)
{
    // Lets see how simeple return works
    Console.WriteLine(SimpleReturn());
    Console.WriteLine(SimpleReturn());
    Console.WriteLine(SimpleReturn());
    Console.WriteLine(SimpleReturn());
}
The reason for this is that the normal return statement does not preserve the state of the function while returning. i.e. every call to this function is a new call and it will return the first value only.
Where as if I replace the return keyword by yield return then the function will become capable of saving its state while returning the value. i.e. when the function is called second time, it will continue the processing from where is has returned in the previous call.
static IEnumerable<int> YieldReturn()
{
    yield return 1;
    yield return 2;
    yield return 3;
}
static void Main(string[] args)
{
    // Lets see how yield return works
    foreach (int i in YieldReturn())
    {
        Console.WriteLine(i);
    }
}
When we run the above code it will return 1,2 and then 3. The only catch while using the yield return statement is that the function should return an IEnumerable and should be called from an iteration block i.e. foreach statement.

Implementing IEnumerable in our custom Collection class

Now in our custom collection classes, if we define a function that will iterate over all the elements in the collection and return then using the yield keyword, we will be able to get hold of all the elements in the the collection.
So let us define our own MyArrayList class and implement IEnumerable interface, which will force us to implement the GetEnumerator function. This function will iterate over the collection and do a yield return on all the elements.
class MyArrayList : IEnumerable
{
    object[] m_Items = null;
    int freeIndex = 0;

    public MyArrayList()
    {
        // For the sake of simplicity lets keep them as arrays
        // ideally it should be link list
        m_Items = new object[100];
    }

    public void Add(object item)
    {
        // Let us only worry about adding the item 
        m_Items[freeIndex] = item;
        freeIndex++;
    }

    // IEnumerable Member
    public IEnumerator GetEnumerator()
    {
        foreach (object o in m_Items)
        {
            // Lets check for end of list (its bad code since we used arrays)
            if(o == null)
            {
                break;
            }

            // Return the current element and then on next function call 
            // resume from next element rather than starting all over again;
            yield return o;
        }
    }
}
This class will now let us enumerate all the elements using a foreach stemement.
static void Main(string[] args)
{
    //Let us now go ahead and use our custom MyArrayList with IEnumerable implemented
    MyArrayList myList = new MyArrayList();

    myList.Add("1");
    myList.Add(2);
    myList.Add("3");
    myList.Add('4');

    foreach (object s in myList)
    {
        Console.WriteLine(s);
    }
}
Note: This class is neither complete not a very good implementation. The only purpose of the sample implementation is to demonstrate the implementation of IEnumerable interface.

Implementing IEnumerable<T> in our custom Generic Collection class

Let us now take this approach a little further and define a generic collection class capable of being enumerated. To do this we need to implement IEnumerable<T> interface.
class MyList<T> : IEnumerable<T>
{
    T[] m_Items = null;
    int freeIndex = 0;

    public MyList()
    {
        // For the sake of simplicity lets keep them as arrays
        // ideally it should be link list
        m_Items = new T[100];
    }

    public void Add(T item)
    {
        // Let us only worry about adding the item 
        m_Items[freeIndex] = item;
        freeIndex++;
    }

    #region IEnumerable<T> Members

    public IEnumerator<T> GetEnumerator()
    {
        foreach (T t in m_Items)
        {
            // Lets check for end of list (its bad code since we used arrays)
            if (t == null) // this wont work is T is not a nullable type
            {
                break;
            }

            // Return the current element and then on next function call 
            // resume from next element rather than starting all over again;
            yield return t;
        }
    }

    #endregion

    #region IEnumerable Members

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        // Lets call the generic version here
        return this.GetEnumerator();
    }

    #endregion
}

This class will now let us enumrate all the elements using a foreach stemement.
static void Main(string[] args)
{
    // Let us first see how we can enumerate an custom MyList<t> class implementing IEnumerable<T>
    MyList<string> myListOfStrings = new MyList<string>();

    myListOfStrings.Add("one");
    myListOfStrings.Add("two");
    myListOfStrings.Add("three");
    myListOfStrings.Add("four");

    foreach (string s in myListOfStrings)
    {
        Console.WriteLine(s);
    }
}
</t>
So now we have a collection class and a generic collectio class that implement IEnumerable and IEnumerable<T> respectively. Althogh These class is neither complete not a very good implementation but they do serve the purpose of the article i.e. to demonstrate the implementation of IEnumerable interface.

Point of interest

What we have tried to do in this article is see how can we implement the IEnumerable and IEnumberable<T> interface. We have looked into the significance of yield keyword. This stuff is known to most experienced C# programmers but the beginners might find it useful. I hope this has been informative.

Explain about CTE and Temp Table and Table Variable

Temp Table or Table variable or CTE are commonly used for storing data temporarily in SQL Server. In this article, you will learn the differences among these three.

CTE

CTE stands for Common Table expressions. It was introduced with SQL Server 2005. It is a temporary result set and typically it may be a result of complex sub-query. Unlike temporary table its life is limited to the current query. It is defined by using WITH statement. CTE improves readability and ease in maintenance of complex queries and sub-queries. Always begin CTE with semicolon.

A sub query without CTE is given below :

  1. SELECT * FROM (
  2. SELECT Addr.Address, Emp.Name, Emp.Age From Address Addr
  3. Inner join Employee Emp on Emp.EID = Addr.EID) Temp
  4. WHERE Temp.Age > 50
  5. ORDER BY Temp.NAME

By using CTE above query can be re-written as follows :

  1. ;With CTE1(Address, Name, Age)--Column names for CTE, which are optional
  2. AS
  3. (
  4. SELECT Addr.Address, Emp.Name, Emp.Age from Address Addr
  5. INNER JOIN EMP Emp ON Emp.EID = Addr.EID
  6. )
  7. SELECT * FROM CTE1 --Using CTE
  8. WHERE CTE1.Age > 50
  9. ORDER BY CTE1.NAME

When to use CTE

  1. This is used to store result of a complex sub query for further use.
  2. This is also used to create a recursive query.

Temporary Tables

In SQL Server, temporary tables are created at run-time and you can do all the operations which you can do on a normal table. These tables are created inside Tempdb database. Based on the scope and behavior temporary tables are of two types as given below-
  1. Local Temp Table

    Local temp tables are only available to the SQL Server session or connection (means single user) that created the tables. These are automatically deleted when the session that created the tables has been closed. Local temporary table name is stared with single hash ("#") sign.
    1. CREATE TABLE #LocalTemp
    2. (
    3. UserID int,
    4. Name varchar(50),
    5. Address varchar(150)
    6. )
    7. GO
    8. insert into #LocalTemp values ( 1, 'Shailendra','Noida');
    9. GO
    10. Select * from #LocalTemp
    The scope of Local temp table exist to the current session of current user means to the current query window. If you will close the current query window or open a new query window and will try to find above created temp table, it will give you the error.
  2. Global Temp Table

    Global temp tables are available to all SQL Server sessions or connections (means all the user). These can be created by any SQL Server connection user and these are automatically deleted when all the SQL Server connections have been closed. Global temporary table name is stared with double hash ("##") sign.
    1. CREATE TABLE ##GlobalTemp
    2. (
    3. UserID int,
    4. Name varchar(50),
    5. Address varchar(150)
    6. )
    7. GO
    8. insert into ##GlobalTemp values ( 1, 'Shailendra','Noida');
    9. GO
    10. Select * from ##GlobalTemp
    Global temporary tables are visible to all SQL Server connections while Local temporary tables are visible to only current SQL Server connection.

Table Variable

This acts like a variable and exists for a particular batch of query execution. It gets dropped once it comes out of batch. This is also created in the Tempdb database but not the memory. This also allows you to create primary key, identity at the time of Table variable declaration but not non-clustered index.
  1. GO
  2. DECLARE @TProduct TABLE
  3. (
  4. SNo INT IDENTITY(1,1),
  5. ProductID INT,
  6. Qty INT
  7. )
  8. --Insert data to Table variable @Product
  9. INSERT INTO @TProduct(ProductID,Qty)
  10. SELECT DISTINCT ProductID, Qty FROM ProductsSales ORDER BY ProductID ASC
  11. --Select data
  12. Select * from @TProduct
  13. --Next batch
  14. GO
  15. Select * from @TProduct --gives error in next batch

Note

  1. Temp Tables are physically created in the Tempdb database. These tables act as the normal table and also can have constraints, index like normal tables.
  2. CTE is a named temporary result set which is used to manipulate the complex sub-queries data. This exists for the scope of statement. This is created in memory rather than Tempdb database. You cannot create any index on CTE.
  3. Table Variable acts like a variable and exists for a particular batch of query execution. It gets dropped once it comes out of batch. This is also created in the Tempdb database but not the memory.

Explain about COM and Interoperability in DotNet

Introduction

Component Object Model is a method to facilitate communication between different applications and languages. There are many other ways to structure software components. What makes COM interesting is that it is a widely accepted interoperability standard. In addition, the standard explains the way the memory should be organized for all the objects.
Interfaces are the contract between the client and the server, i.e. an interface is the way in which an object exposes its functionality to the outside world. In COM, an interface is a table of pointers to functions implemented by the object. The table represents the interface, and the functions to which it points are the methods of that interface.

Creating COM components in .NET

Creating COM components in .NET is not that difficult as in C++. The following steps explain the way to create the COM server in C#:
  1. Create a new Class Library project.
  2. Create a new interface, say IManagedInterface, and declare the methods required. Then provide the Guid (this is the IID) for the interface using the GuidAttribute defined in System.Runtime.InteropServices. The Guid can be created using the Guidgen.exe. [Guid("3B515E51-0860-48ae-B49C-05DF356CDF4B")]
  3. Define a class that implements this interface. Again provide the Guid (this is the CLSID) for this class also.
  4. Mark the assembly as ComVisible. For this go to AssemblyInfo.cs file and add the following statement [assembly: ComVisible (true)]. This gives the accessibility of all types within the assembly to COM.
  5. Build the project. This will generate an assembly in the output path. Now register the assembly using regasm.exe (a tool provided with the .NET Framework)- regasm \bin\debug\ComInDotNet.dll \tlb:ComInDotNet.tlb This will create a TLB file after registration.
  6. Alternatively this can be done in the Project properties -> Build -> check the Register for COM interop.
The COM server is ready. Now a client has to be created. It can be in any language. If the client is .NET, just add the above created COM assembly as reference and use it.

The following steps explain the method to create an unmanaged client. Here the client is in VC++ 6.0.
  1. Create an MFC AppWizard EXE using the wizard in MSDEV 6.0.
  2. Import the COM server (TLB file generated by regasm.exe) using the #import directive. #import “ComInDotNet.tlb” no_namespace named_guids raw_interfaces_only.
  3. Now the COM library should be loaded using the CoInitialize and component can be created using CoCreateInstance.
  4. Next the methods defined in the COM Server can be invoked. pInterface->Execute(“blah blah blah”);    
  5. What is COM?
    Microsoft COM (Component Object Model) technology in the Microsoft Windows-family of Operating Systems enables software components to communicate. COM is used by developers to create re-usable software components, link components together to build applications, and take advantage of Windows services. COM objects can be created with a variety of programming languages. Object-oriented languages, such as C++, provide programming mechanisms that simplify the implementation of COM objects. The family of COM technologies includes COM+, Distributed COM (DCOM) and ActiveX® Controls.

    Microsoft provides COM interfaces for many Windows application programming interfaces such as Direct Show, Media Foundation, Packaging API, Windows Animation Manager, Windows Portable Devices, and Microsoft Active Directory (AD).

    COM is used in applications such as the Microsoft Office Family of products. For example COM OLE technology allows Word documents to dynamically link to data in Excel spreadsheets and COM Automation allows users to build scripts in their applications to perform repetitive tasks or control one application from another.
    What's new in .NET Framework 3.5 SP1?
    SP1 advances the art of application development
    The new ADO.NET Entity Framework feature in SP1 offers developers a model-based paradigm and a rich, standards-based framework for creating data-oriented applications shared across multiple applications and platforms. The separation of presentation, data, and business logic used in concert with a single data model will enable developers to spend less time writing plumbing code and more time refining business logic.

    SP1 makes data-driven programming easier
    SP1 offers developers support for ASP.NET Dynamic Data, which provides a rich scaffolding framework that enables rapid data-driven development. Since ASP.NET takes care of creating the presentation layer, a fully functional Website is output and ready for customization without the developer writing a single line of code. Further, with ADO.NET Data Services, Web developers can create RESTful Web 2.0-style applications that have better server scalability and improved caching support.

    SP1 is the fastest and easiest way to deploy Windows applications
    With the .NET Framework Client Profile, a small subset of the Framework that powers client applications, developers can offer their end users a dramatically streamlined and rapid application download experience. In addition, improvements in SP1 result in dramatic reductions in cold start times, allowing developers to serve a broader set of customers with varying hardware profiles

    Summary

    This paper provides the technical overview of .NET and COM interoperability. It describes how .NET components can communicate with existing COM components without migrating those COM components into .NET components, thus helping the migration cost and business systems. This paper also provides an overview of marshalling. The intended audience is a development team that wishes to interact with COM and .NET applications. (This paper assumes that the reader has the fundamental knowledge of COM and .NET)

    Introduction

    From the time Microsoft engineers started working on the ideas behind COM in 1998, COM went through quite an evolution. Once .NET was released everything was about the CLR. Those business systems made lot of investments on those COM developments and they may not be willing to invest more money to build their components into .NET. Also this will make a severe impact in productivity.
    Fortunately, switching from COM to .NET involves no such radical loss of productivity. The concept of providing bridge between .NET and COM components is .NET-COM interoperability. Microsoft .NET Framework provides system, tools, and strategies that enable strong integration with past technologies and allow legacy code to be integrated with new .NET components. It provides a bridge between the .NET and COM and vice versa.
    There are two key concepts that make it much easier to move from COM development to .NET development, without any loss of code base or productivity.
  6. Interaction with COM components from .NET
  7. Interaction with .NET components from COM
Before going further, this paper will describe about the basic communication fundamentals of COM and .NET components.

Communication between Object and Client

COM is a binary reusable object which exposes its functionality to other components. When a client object asks for instances of server object, the server instantiates those objects and handout references to the client. So, a COM component can act as a binary contract between caller and callee. This binary contract is defined in a document known as Type library. The Type library describes to a potential client the services available from a particular server. Each COM components will expose a set of interfaces through which the communication between COM components will occurs.
The following diagram shows the communication between a client and a COM object.

Fig.1 Communication between client and a COM object
In the above figure the IUnknown and IDispatch are the interfaces and QueryInterface, AddRef, Release, etc., are the methods exposed by those interfaces.
The communication between the .NET objects occurs through Objects, there are no such interfaces for communication. So, in .NET component, there is no type libraries, instead they deal with assemblies. Assembly is a collection of types and resources that are built to work together and form a logical unit of functionality. All the information related to the assembly will be held in assembly metadata. Unlike the communication between COM components, the communication between .NET components is Object based.

Calling COM components from .NET Client

Generally COM components will expose interfaces to communicate with other objects. A .NET client cannot directly communicate with a COM component because the interfaces exposed by a COM component may not be read by the .NET application. So, to communicate with a COM component, the COM component should be wrapped in such a way that the.NET client application can understand the COM component. This wrapper is known as Runtime Callable Wrapper (RCW).
The .NET SDK provides Runtime Callable Wrapper (RCW) which wraps the COM components and exposes it into to the .NET client application.

Fig.2 calling a COM component from .NET client
To communicate with a COM component, there should be Runtime Callable Wrapper (RCW). RCW can be generated by using VS.NET or by the use of TlbImp.exe utility. Both the ways will read the type library and uses System.Runtime.InteropServices.TypeLibConverter class to generate the RCW. This class reads the type library and converts those descriptions into a wrapper (RCW). After generating the RCW, the .NET client should import its namespace. Now the client application can call the RCW object as native calls.
When a client calls a function, the call is transferred to the RCW. The RCW internally calls the native COM function coCreateInstance there by creating the COM object that it wraps. The RCW converts each call to the COM calling convention. Once the object has been created successfully, the .NET client application can access the COM objects as like native object calls.

Calling .NET components from COM Client

When a COM client requests a server, first it searches in the registry entry and then the communication starts. Calling a .NET component from a COM component is not a trivial exercise. The .NET objects communicate through Objects. But the Object based communication may not be recognized by the COM clients. So, to communicate with the .NET component from the COM component, the .NET component should be wrapped in such a way that the COM client can identify this .NET component. This wrapper is known as COM Callable Wrapper (CCW). The COM Callable Wrapper (CCW) will be used to wrap the .NET components and used to interact with the COM clients.
CCW will be created by the .NET utility RegAsm.exe. This reads metadata of the .NET component and generates the CCW. This tool will make a registry entry for the .NET components.

Fig.3 calling a .NET component from COM client
Generally COM client instantiates objects through its native method coCreateInstance. While interacting with .NET objects, the COM client creates .NET objects by coCreateInstance through CCW.
Internally, when coCreateInstance is called, the call will redirect to the registry entry and the registry will redirect the call to the registered server, mscoree.dll. This mscoree.dll will inspect the requested CLSID and reads the registry to find the .NET class and the assembly that contains the class and rolls a CCW on that .NET class.
When a client makes a call to the .NET object, first the call will go to CCW. The CCW converts all the native COM types to their .NET equivalents and also converts the results back from the .NET to COM.

Programming model comparison of .NET-COM interoperability

The following table compares the .NET and COM based component programming models.

.NET COM
Object based communication Interface based communication
Garbage Collector to manage memory Reference count will be used to manage memory
Type Standard objects Binary Standard objects
Objects are created by normal new operator Objects are created by coCreateInstance
Exceptions will be returned HRESULT will be returned
Object info resides in assembly files Object info resides in Type library

Before the application starts to communicate, there are some technical constraints associated with this. When an object is transmitted to a receiver which is in a separate machine/process (managed/unmanaged) space, the object may need to undergo a transformation according to the native type to make it suitable for use by the recipient. That is the object will be converted into a recipient readable form. This process of converting an object between types when sending it across contexts is known as marshaling. The next section of the paper will gives an overview of marshalling in .NET.

.NET Marshalling

Thus .NET runtime automatically generates code to translate calls between managed code and unmanaged code. While transferring calls between these two codes, .NET handles the data type conversion also. This technique of automatically binding with the server data type to the client data type is known as marshalling. Marshaling occurs between managed heap and unmanaged heap. For example, Fig.4 shows a call from the .NET client to a COM component. This sample call passes a .NET string from the client. The RCW converts this .NET data type into the COM compatible data type. In this case COM compatible data type is BSTR. Thus the RCW converts the .NET string into COM compatible BSTR. This BSTR will be passed to the object and the required calls will be made. The results will be returned to back to the RCW. The RCW converts this COM compatible result to .NET native data type.

Fig.4 Sample diagram for marshalling
Logically the marshalling can be classified into 2 types.
  1. Interop marshalling
  2. COM marshalling
If a call occurs between managed code and unmanaged code with in the same apartment, Interop marshaler will play the role. It marshals data between managed code and unmanaged code.
In some scenarios COM component may be running in different apartment threads. In those cases i.e., calling between managed code and unmanaged code in different apartments or process, both Interop marshaler and COM marshaler are involved.

Interop marshaler

When the server object is created in the same apartment of client, all data marshaling is handled by Interop marshaling.

Fig.5 Sample diagram for same apartment marshalling

COM marshaler

COM marshaling involved whenever the calls between managed code and unmanaged code are in different apartments. For eg., when a .NET client (with the default apartment settings) communicates with a COM component (whichever developed in VB6.0), the communication occurs through proxy and stub because both the objects will be running in different apartment threads. (The default apartment settings of .NET objects are STA and the components which are developed by VB6.0 are STA). Between these two different apartments COM marshaling will occurs and with in the apartment Interop marshaling will occurs. Fig.6 shows this kind of marshaling.
This kind of different apartment communication will impact the performance. The apartment settings of the managed client can be changed by changing the STAThreadAttribute / MTAThreadAttribute / Thread.ApartmentState property. Both the codes can run in a same apartment, by making the managed code’s thread to STA. (If the COM component is set as MTA, then cross marshaling will occurs.)

Fig.6 Sample diagram for cross apartment marshalling
In the above scenario, the call with in different apartments will occur by COM marshaling and the call between managed and unmanaged code will occur by Interop marshaling.

Conclusion

Thus the communication between .NET applications and COM applications occurs through RCW and CCW.
As you have seen, COM applications can implement .NET types to achieve type compatibility or a .NET type can implement COM interfaces to achieve binary compatibility with related coclasses.
Although the managed clients can interact with the unmanaged objects, the managed client expects that the unmanaged object should act exactly the same as managed object.
When developing against the unmanaged component through COM interoperability, managed code developers will not be able to use some features of .NET like parameterized constructors, static methods, inheritance, etc., migrating an existing component or writing a managed wrapper will make the component easier to use for managed code developers. In some cases, the developer wants to migrate parts of the application to .NET so that application can take advantage of the new features that the .NET Framework offers. For example, ASP .NET provides advanced data binding, browser-dependent user interface generation, and improved configuration and deployment. The designer should evaluate when the value of bringing these new features in to the application outweigh the cost of code migration.
  1.                                     

Source contains no data rows Exception in DataTable using LINQ

I was using following code to get a filtered DataTable

DataTable DT = new DataTable();

DT = NewMobileFa.GetNewMobile().AsEnumerable().Where(r => arrList.Contains(r.Field<int>("NewMobileID")) && r.Field<string>("Status") == "OF").CopyToDataTable();

Above code gave me the error Source contains no data rows. Which is correct and actually there is no data.

I needed to avoid the exception even though there is no data. Below code solved the issue.

DT = NewMobileFa.GetNewMobile().AsEnumerable().Where(r => arrList.Contains(r.Field<int>("NewMobileID")) && r.Field<string>("Status") == "OF").AsDataView().ToTable();

LINQ Joins Examples

There are Different Types of SQL Joins which are used to query data from more than one tables. In this article, I would like to share how joins work in LINQ. LINQ has a JOIN query operator that provide SQL JOIN like behavior and syntax. Let's see how JOIN query operator works for joins. This article will explore the SQL Joins with C# LINQ.
  1. INNER JOIN
  2. LEFT OUTER JOIN
  3. CROSS JOIN
  4. GROUP JOIN
The JOIN query operator compares the specified properties/keys of two collections for equality by using the EQUALS keyword. By default, all joins queries written by the JOIN keyword are treated as equijoins.

LINQ PAD for running and debugging LINQ Query

I am a big fan of LINQ Pad since it allow us to run LINQ to SQL and LINQ to Entity Framework query and gives the query output. Whenever, I need to write LINQ to SQL and LINQ to Entity Framework query then, I prefer to write and run query on LINQ PAD. By using LINQ PAD, you can test and run your desired LINQ query and avoid the head-ache for testing LINQ query with in Visual Studio. You can download the LINQ Pad script used in this article by using this link.
In this article, I am using LINQ PAD for query data from database. It is simple and useful. For more help about LINQ PAD refer the link. You can download the database script used in this article by using this link. Suppose we following three tables and data in these three tables is shown in figure.

INNER JOIN

Inner join returns only those records or rows that match or exists in both the tables.

C# Code

  1. var q=(from pd in dataContext.tblProducts join od in dataContext.tblOrders on pd.ProductID equals od.ProductID orderby od.OrderID select new { od.OrderID,
  2. pd.ProductID,
  3. pd.Name,
  4. pd.UnitPrice,
  5. od.Quantity,
  6. od.Price,
  7. }).ToList();

LINQ Pad Query

INNER JOIN among more than two tables

Like SQL, we can also apply join on multiple tables based on conditions as shown below.

C# Code

  1. var q=(from pd in dataContext.tblProducts join od in dataContext.tblOrders on pd.ProductID equals od.ProductID join ct in dataContext.tblCustomers on od.CustomerID equals ct.CustID orderby od.OrderID select new { od.OrderID,
  2. pd.ProductID,
  3. pd.Name,
  4. pd.UnitPrice,
  5. od.Quantity,
  6. od.Price,
  7. Customer=ct.Name //define anonymous type Customer
  8. }).ToList();

LINQ Pad Query

INNER JOIN On Multiple Conditions

Sometimes, we required to apply join on multiple coditions. In this case, we need to make two anonymous types (one for left table and one for right table) by using new keyword then we compare both the anonymous types.

C# Code

  1. var q=(from pd in dataContext.tblProducts join od in dataContext.tblOrders on pd.ProductID equals od.ProductID join ct in dataContext.tblCustomers on new {a=od.CustomerID,b=od.ContactNo} equals new {a=ct.CustID,b=ct.ContactNo} orderby od.OrderID select new { od.OrderID,
  2. pd.ProductID,
  3. pd.Name,
  4. pd.UnitPrice,
  5. od.Quantity,
  6. od.Price,
  7. Customer=ct.Name //define anonymous type Customer
  8. }).ToList();

LINQ Pad Query

NOTE

  1. Always remember, both the anonymous types should have exact same number of properties with same name and datatype other wise you will get the compile time error "Type inferencce failed in the call to Join".
  2. Both the comparing fields should define either NULL or NOT NULL values.
  3. If one of them is defined NULL and other is defined NOT NULL then we need to do typecasting of NOT NULL field to NULL data type like as above fig.

LEFT JOIN or LEFT OUTER JOIN

LEFT JOIN returns all records or rows from left table and from right table returns only matched records. If there are no columns matching in the right table, it returns NULL values.
In LINQ to achieve LEFT JOIN behavior, it is mandatory to use "INTO" keyword and "DefaultIfEmpty()" method. We can apply LEFT JOIN in LINQ like as :

C# Code

  1. var q=(from pd in dataContext.tblProducts join od in dataContext.tblOrders on pd.ProductID equals od.ProductID into t from rt in t.DefaultIfEmpty() orderby pd.ProductID select new { //To handle null values do type casting as int?(NULL int)
  2. //since OrderID is defined NOT NULL in tblOrders
  3. OrderID=(int?)rt.OrderID,
  4. pd.ProductID,
  5. pd.Name,
  6. pd.UnitPrice,
  7. //no need to check for null since it is defined NULL in database
  8. rt.Quantity,
  9. rt.Price,
  10. }).ToList();

LINQ Pad Query

CROSS JOIN

Cross join is a cartesian join means cartesian product of both the tables. This join does not need any condition to join two tables. This join returns records or rows that are multiplication of record number from both the tables means each row on left table will related to each row of right table.
In LINQ to achieve CROSS JOIN behavior, there is no need to use Join clause and where clause. We will write the query as shown below.

C# Code

  1. var q = from c in dataContext.Customers from o in dataContext.Orders select new { c.CustomerID,
  2. c.ContactName,
  3. a.OrderID,
  4. a.OrderDate
  5. };

LINQ Pad Query

GROUP JOIN

Whene a join clause use an INTO expression, then it is called a group join. A group join produces a sequence of object arrays based on properties equivalence of left collection and right collection. If right collection has no matching elements with left collection then an empty array will be produced.

C# Code

  1. var q=(from pd in dataContext.tblProducts join od in dataContext.tblOrders on pd.ProductID equals od.ProductID into t orderby pd.ProductID
  2. select new
  3. {
  4. pd.ProductID,
  5. pd.Name,
  6. pd.UnitPrice,
  7. Order=t
  8. }).ToList();

LINQ Pad Query

Basically, GROUP JOIN is like as INNER-EQUIJOIN except that the result sequence is organized into groups.

GROUP JOIN As SubQuery

We can also use the result of a GROUP JOIN as a subquery like as:

C# Code

  1. var q=(from pd in dataContext.tblProducts join od in dataContext.tblOrders on pd.ProductID equals od.ProductID into t from rt in t where rt.Price>70000 orderby pd.ProductID select new { rt.OrderID,
  2. pd.ProductID,
  3. pd.Name,
  4. pd.UnitPrice,
  5. rt.Quantity,
  6. rt.Price,
  7. }).ToList();

LINQ Pad Query

What do you think?
I hope you will enjoy these valuable tricks while programming with LINQ to SQL. I would like to have feedback from my blog readers. Your valuable feedback, question, or comments about this article are always welcome.