Search This Blog
2009-06-28
Implementation of Builder Pattern
using System;
using System.Collections.Generic;
using System.Text;
namespace BuilderPattern
{
interface IBuilder
{
void DoIt();
}
class BuilderA:IBuilder
{
public void DoIt()
{
Console.WriteLine("BuilderA is called");
}
}
class BuilderB : IBuilder
{
public void DoIt()
{
Console.WriteLine("BuilderB is called");
}
}
class Director
{
public void Construct(IBuilder builder)
{
builder.DoIt();
}
}
class Program
{
static void Main(string[] args)
{
Director d = new Director();
IBuilder build = new BuilderA();
d.Construct(build);
Console.ReadLine();
}
}
}
Output:
Implementation of Singleton Pattern
using System;
using System.Collections.Generic;
using System.Text;
namespace SingletonPattern
{
public class Singleton
{
private static Singleton singletonInstance;
// Constructor is 'protected',so intance can't be created outside,
//only the createInstance() create the instance of Singleton class
protected Singleton()
{
}
public static Singleton createInstance()
{
if (singletonInstance == null)
{
singletonInstance = new Singleton();
}
return singletonInstance;
}
}
class Program
{
static void Main(string[] args)
{
// Constructor is protected -- cannot use new
Singleton s1 = Singleton.createInstance();
Singleton s2 = Singleton.createInstance();
// Test for same instance
if (s1 == s2)
{
Console.WriteLine("Objects are the same instance");
}
Console.ReadLine();
}
}
}
Output:
Implementation of factory Pattern
using System;
using System.Collections.Generic;
using System.Text;
namespace FactoryPattern
{
interface IBase
{
void DoIt();
}
class Derived1:IBase
{
public void DoIt()
{
Console.WriteLine("Derived1 Method is called");
}
}
class Derived2:IBase
{
public void DoIt()
{
Console.WriteLine("Derived2 Method is called");
}
}
class Factory
{
public IBase getObject(int type)
{
IBase objIBase = null;
switch (type)
{
case 1:
objIBase = new Derived1();
break;
case 2:
objIBase = new Derived2();
break;
}
return objIBase;
}
}
class Program
{
static void Main(string[] args)
{
Factory objFactory = new Factory();
IBase objIbase = objFactory.getObject(1);
objIbase.DoIt();
Console.ReadLine();
}
}
}
Output:
Diagram/Description
Static Constructor
C# supports two types of Constructor
1.Class Constructor or Static Constructor-used to initialize static data members as soon as the class is referenced first time
2.Instance Constructor or non-Static Constructor-used to create an instance of that class with new keyword.
Static Data Member can be initialized at the time of their declaration(clsWithoutStaticConstructor in the following example) but there are times when value of one static member (clsWithStaticConstructor in the following example)may depend upon the value of another static member.
using System;
using System.Collections.Generic;
using System.Text;
namespace StaticConstructor
{
class clsWithoutStaticConstructor
{
private static int numStatData = 8;
public static int StatData
{
get { return numStatData; }
}
public static void print()
{
Console.WriteLine("Static Data :" + StatData);
}
}
class clsWithStaticConstructor
{
private static int numStatData2;
static clsWithStaticConstructor()
{
if (clsWithoutStaticConstructor.StatData < 10)
{
numStatData2 = 10;
}
else
{
numStatData2 = 100;
}
Console.WriteLine("Static Constructor is called...");
}
public static void print2()
{
Console.WriteLine("Static Data :" + numStatData2);
Console.ReadLine();
}
}
class Program
{
static void Main(string[] args)
{
clsWithoutStaticConstructor.print();
clsWithStaticConstructor.print2();
}
}
}
Output :
In the above example "numStatData2" in "clsWithStaticConstructor" is initialized based on the value of clsWithoutStaticConstructor.StatData .since StatData in the clsWithoutStaticConstructor is initilized to 8 so the value of numStatData2 is set to 10.
Static Constructor executes:
-before any instance of the class is created.
-before any of the static members for the class are referenced.
-after the static field initializers(if any) for the class.
-atmost one time.
and a static constructor does not take access modifiers or have parameter
2009-06-22
What is new in .NET 2.0
Generics
Iterators
Anonymous methods
Partial classes
generics :It is a programming language mechanism by which a single piece of code (function, object, interface, etc.) can manipulate many different data types.
Code Snippent:
class MyArrayList<ItemType>
{
private ItemType[] items = new ItemType[10];
private int count;
public void Add(ItemType item)
{
items[count++] = item;
}
public ItemType GetItem(int index)
{
return items[index];
}
}
To Call this method:
MyArrayList<int> iList = new MyArrayList
MyArrayList<string> sList = new MyArrayList
iList.Add(25);
int iValue = iList.GetItem(0);
sList.Add("Manab");
string sValue = sList.GetItem(0);
Using Methods:
Generic methods will allow you to pass one or more data types. An Example is given below.
public class MyClass
{
public ItemType MyMethod<ItemType>(ItemType item)
{
return item;
}
}
To Call the method
MyClass mc = new MyClass();
int i= mc.MyMethod<int>(32);
Response.Write(i.ToString());
C#Generics has the following advantages:
1.The Program becomes statically typed, so errors are discovered at compile-time.
2.No runtime casts are required and the program runs faster.
3.Primitive type values (e.g int) need not be wrapped. Hence the program is faster and uses less space.
iterator : An iterator is an object that allows a programmer to traverse through all the elements of a collection, regardless of its specific implementation.
foreach Loops Based on an Enumerator Pattern
// Implementation
ArrayList list = new ArrayList();
// ...
foreach(object obj in list)
{
DoSomething(obj);
}
// Translation through compiler
Enumerator e = list.GetEnumerator();
while(e.MoveNext())
{
object obj = e.Current;
DoSomething(obj);
}
Anonymous Methods:Anonymous methods let you define methods, usually delegates, inline with the declaration of the event.
You can replace this code:
button.Click += new EventHandler (this.bClick);
// elsewhere
private void bClick (sender, e)
{
MessageBox.Show ("click");
}
with the code given below:
button.Click +=new EventHandler (object sender, EventArgs e)
{
MessageBox.Show ("click");
}
Partial Classes:This feature allows you to split a particular class into two or more separate files. For this purpose, every part of the class is marked with the new modifier partial. The compiler looks for the marked parts and merges them into one complete implementation. You'll see no difference at run time. The assembly of the code parts requires all elements be in the same project and a parallel compilation. In addition, the classes have to match logically and must be identical regarding their modifiers, supported interfaces, and so on.
using System;
public partial class Foo
{
public void SomeMethod()
{
}
}
// foo2.cs
using System;
public partial class Foo
{
public void SomeOtherMethod()
{
}
}
Web Editor for ASP.NET
Microsoft AJAX (ASP.NET AJAX Extensions) introduces a new implementation model for server controls with related scripts. This article discusses how to create an HTML editor server control specifically for the Microsoft AJAX environment. The reader can also download the source code, including a sample web page, and view an online demo from the following URL.
http://69.10.233.10/KB/ajax/HtmlEditor.aspx?display=Print
2009-06-18
Basics Of Windows Communication Foundation
Windows Communication Foundation (WCF) is an SDK for developing and deploying services on Windows. WCF provides a runtime environment for services, enabling you to expose CLR types as services, and to consume other services as CLR types.
WCF is part of .NET 3.0 and requires .NET 2.0, so it can only run on systems that support it.
WCF is a unification of .NET framework communication technologies which unites the following technologies:-
-NET remoting
-MSMQ
-Web services
-COM+
What is service and client in perspective of data communication?
A service is a unit of functionality exposed to the world. The client of a service is merely the party consuming the service.
What is ABCs Of WCF?
Hosts and Clients communicate with each other by agreeing on the ABCs.ABC indicates three things:
-Address:The location Of the service
-Binding:WCF Ships with a number of different bindings that specify network protocols
-Contract:A description of each method exposed from the WCF Service.
<system.serviceModel>
<services>
<service name="MyNameService" behaviorConfiguration="MyNameServiceBehavior">
<endpoint address="" binding="wsHttpBinding" contract="IMyService"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MyNameServiceBehavior">
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
What is endpoint in WCF?
Every service must have Address that defines where the service resides, Contract that defines what the service does and a Binding that defines how to communicate with the service. In WCF the relationship between Address, Contract and Binding is called Endpoint.
The Endpoint is the fusion of Address, Contract and Binding.
What is address in WCF and how many types of transport schemas are there in WCF?
Address is a way of letting client know that where a service is located. In WCF, every service is associated with a unique address. This contains the location of the service and transport schemas.
WCF supports following transport schemas
-HTTP
-TCP
-Peer network
-IPC (Inter-Process Communication over named pipes)
-MSMQ
The sample address for above transport schema may look like
http://localhost:85
http://localhost:85/MyService
net.tcp://localhost:85/MyService
net.pipe://localhost/MyPipeService
net.msmq://localhost/private/MyMsMqService
net.msmq://localhost/MyMsMqService
What is binding and how many types of bindings are there in WCF?
A binding defines how an endpoint communicates to the world. A binding defines the transport (such as HTTP or TCP) and the encoding being used (such as text or binary). A binding can contain binding elements that specify details like the security mechanisms used to secure messages, or the message pattern used by an endpoint.
WCF supports nine types of bindings.
-Basic binding
Offered by the BasicHttpBinding class, this is designed to expose a WCF service as a legacy ASMX web service, so that old clients can work with new services. When used by the client, this binding enables new WCF clients to work with old ASMX services.
-TCP binding
Offered by the NetTcpBinding class, this uses TCP for cross-machine communication on the intranet. It supports a variety of features, including reliability, transactions, and security, and is optimized for WCF-to-WCF communication. As a result, it requires both the client and the service to use WCF.
-Peer network binding
Offered by the NetPeerTcpBinding class, this uses peer networking as a transport. The peer network-enabled client and services all subscribe to the same grid and broadcast messages to it.
-IPC binding
Offered by the NetNamedPipeBinding class, this uses named pipes as a transport for same-machine communication. It is the most secure binding since it cannot accept calls from outside the machine and it supports a variety of features similar to the TCP binding.
-Web Service (WS) binding
Offered by the WSHttpBinding class, this uses HTTP or HTTPS for transport, and is designed to offer a variety of features such as reliability, transactions, and security over the Internet.
-Federated WS binding
Offered by the WSFederationHttpBinding class, this is a specialization of the WS binding, offering support for federated security.
-Duplex WS binding
Offered by the WSDualHttpBinding class, this is similar to the WS binding except it also supports bidirectional communication from the service to the client.
-MSMQ binding
Offered by the NetMsmqBinding class, this uses MSMQ for transport and is designed to offer support for disconnected queued calls.
-MSMQ integration binding
Offered by the MsmqIntegrationBinding class, this converts WCF messages to and from MSMQ messages, and is designed to interoperate with legacy MSMQ clients.
What are contracts in WCF?
In WCF, all services expose contracts. The contract is a platform-neutral and standard way of describing what the service does.
WCF defines four types of contracts.
-1.Service contracts:
Describe which operations the client can perform on the service.
There are two types of Service Contracts.
--a)ServiceContract - This attribute is used to define the Interface.
--b)OperationContract - This attribute is used to define the method inside Interface.
[ServiceContract]
interface IMyContract
{
[OperationContract]
string MyMethod( );
}
class MyService : IMyContract
{
public string MyMethod( )
{
return "Hello World";
}
}
-2.Data contracts:Define which data types are passed to and from the service. WCF defines implicit contracts for built-in types such as int and string, but we can easily define explicit opt-in data contracts for custom types.
There are two types of Data Contracts.
--a)DataContract - attribute used to define the class
--b)DataMember - attribute used to define the properties.
[DataContract]
class Contact
{
[DataMember]
public string FirstName;
[DataMember]
public string LastName;
}
If DataMember attributes are not specified for a properties in the class, that property can't be passed to-from web service.
-3.Fault contracts:Define which errors are raised by the service, and how the service handles and propagates errors to its clients.
-4.Message contracts :Allow the service to interact directly with messages. Message contracts can be typed or untyped, and are useful in interoperability cases and when there is an existing message format we have to comply with.
Where we can host WCF services?
Every WCF services must be hosted somewhere. There are three ways of hosting WCF services.
They are
-1. IIS
-2. Self Hosting
-3. WAS (Windows Activation Service)
How to deal with operation overloading while exposing the WCF services?
By default overload operations (methods) are not supported in WSDL based operation. However by using Name property of OperationContract attribute, we can deal with operation overloading scenario.
[ServiceContract]
interface ICalculator
{
[OperationContract(Name = "AddInt")]
int Add(int arg1,int arg2);
[OperationContract(Name = "AddDouble")]
double Add(double arg1,double arg2);
}
What is the difference WCF and Web services?
-Web services can only be invoked by HTTP. While WCF Service or a WCF component can be invoked by any protocol and any transport type. Second web services are not flexible. However, WCF Services are flexible.
-If you make a new version of the service then you need to just expose a new end. Therefore, services are agile and which is a very practical approach looking at the current business trends.
How to set the timeout property for the WCF Service client call?
The timeout property can be set for the WCF Service client call using binding tag.
<client>
<endpoint
...
binding = "wsHttpBinding"
bindingConfiguration = "LongTimeout"
...
/>
</client>
<bindings>
<wsHttpBinding>
<binding name = "LongTimeout" sendTimeout = "00:04:00"/>
</wsHttpBinding>
</bindings>
If no timeout has been specified, the default is considered as 1 minute.
What is Proxy and how to generate proxy for WCF Services?
The proxy is a CLR class that exposes a single CLR interface representing the service contract. The proxy provides the same operations as service's contract, but also has additional methods for managing the proxy life cycle and the connection to the service. The proxy completely encapsulates every aspect of the service: its location, its implementation technology and runtime platform, and the communication transport.
The proxy can be generated using Visual Studio by right clicking Reference and clicking on Add Service Reference. This brings up the Add Service Reference dialog box, where you need to supply the base address of the service (or a base address and a MEX URI) and the namespace to contain the proxy.
Proxy can also be generated by using SvcUtil.exe command-line utility. We need to provide SvcUtil with the HTTP-GET address or the metadata exchange endpoint address and, optionally, with a proxy filename. The default proxy filename is output.cs but you can also use the /out switch to indicate a different name.
SvcUtil http://localhost/MyService/MyService.svc /out:Proxy.cs
When we are hosting in IIS and selecting a port other than port 80 (such as port 88), we must provide that port number as part of the base address:
SvcUtil http://localhost:88/MyService/MyService.svc /out:Proxy.cs
-------------------------------------------------------------------------------------
Resource:http://www.dotnetfunda.com/interview/ShowCatQuestion.aspx?start=0&page=1&category=74
2009-06-17
Create A Step by Step WCF Application
-1.getName:Which will take two input string parameter first name and the last name and returns a string which is a concatination of both two input string
-2.getMessage:Which will take one input string parameter and returns the same string appending another string "Message :" as a prefix
I have used Microsoft Visual Web Developer 2008 Express Edition for creating service and Microsoft Visual C# 2008 Express Edition for creating a windows application to invoke that service.
So it is very Simple.Let's Start
Step 1.Create New WCF Service
Open Microsoft Visual Web Developer 2008 Express Edition to create a New Website
Go to File->New Web Site and you will see a template called WCF Service.Select this template and put "MyWCFService" as a File Name
Step 2.Define ServiceContract and OperationContract
Open the IService.cs under App_Code,Delete all lines of code except the namespace portion and copy the following code after namespace.
[ServiceContract]
public interface IMyService
{
[OperationContract]
string getName(string fName, string lName);
[OperationContract]
string getMessage(string Message);
}
Step 3.Implement the Service
Open Service.cs under App_Code ,similarly delete all lines of code except the namespace.Create a new class MyNameService and implement IMyService.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
public class MyNameService : IMyService
{
#region IMyService Members
public string getName(string fName, string lName)
{
return fName + " " + lName;
}
public string getMessage(string Message)
{
return "Message :" + Message;
}
#endregion
}
Step 4.Create Service Defination File(.SVC)
Open Service.svc change service to "MyNameService".
<%@ ServiceHost Language="C#" Debug="true" Service="MyNameService" CodeBehind="~/App_Code/Service.cs" %>
Step 5.Edit web.config file for service hosting
Go to web.config.Within system.serviceModel you have a services.Under services you will get service tag,
-Change the name to "MyNameService" which is a user defined class under Service.cs that impement IMyService.
-Change the behaviorConfiguration to MyNameServiceBehavior
Go to the end point tag within service tage,
-Change contract to IMyService which is the name of your interface.
Step 6.Enable metadata for client access
Within this web.config file go To serviceBehaviors under behaviors,Go To behavior tag
-Within the behavior tag change the name to MyNameServiceBehavior which you have mention in the behaviorConfiguration at step 5.
-Within serviceDebug tag set includeExceptionDetailInFaults=true
The system.serviceModel will look like as follows(Step 5 and Step 6)
<system.serviceModel>
<services>
<service name="MyNameService" behaviorConfiguration="MyNameServiceBehavior">
<endpoint address="" binding="wsHttpBinding" contract="IMyService"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MyNameServiceBehavior">
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Step 7.Build and Test the application
Select Service.svc and right click.Click on "Set As Start Page"
Now run your application by clicking F5.You can see the following page when you run it.
Step 8.Generate a configuration file and a code file that contains the client class
Go to command prompt (type cmd in Start menu->run)
To go to the folder which contain SvcUtil.exe,Type
cd C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin
run the following command
svcutil.exe http://localhost:1805/MyWCFService/Service.svc?wsdl
You can get the url from the output window(web site) generated at step 7
After executing the command ,you will get following two files within the folder C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin or the folder which contain SvcUtil.exe
-1.MyNameService.cs
-2.output.config
Step 9.Create A client application which will invoke your WCF Service
Create a windows application "MyWCFClient" in different .NET IDE
Step 10.Add Service Reference
Right click on your solution and click on "Add Service Reference"
Put the URL generated at step 7.
Click on GO.
Type "MyServiceReference" in a Namespace textbox.
Now Click OK
Now it will generate/Modify two files
-MyServiceReference under Service References folder
-app.config
Step 11.Copy Configuratin and code file
Copy MyNameService.cs and output.config generated at Step 8. Paste it in the root folder of your windows application(MyWCFClient)
Step 12.Invoke the WCF Service
Call your WCF Service(MyService) in a button click event.Create an object of MyServiceClient and call two methods getName and getMessage that is declared in IMyService at step 2 and implemented in MyNameService at step 3
private void button1_Click(object sender, EventArgs e)
{
MyServiceClient msc = new MyServiceClient();
MessageBox.Show(msc.getName("Manab", "Basu"));
MessageBox.Show(msc.getMessage("Tested"));
}
Step 13.Modify the app.config
Open the app.config and go to the endpoint tage within client under system.serviceModel.
Modify contract="MyServiceReference.IMyService" to contract="IMyService"
The file will look like as follows
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IMyService" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
allowCookies="false">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00"
enabled="false" />
<security mode="Message">
<transport clientCredentialType="Windows" proxyCredentialType="None"
realm="" />
<message clientCredentialType="Windows" negotiateServiceCredential="true"
algorithmSuite="Default" establishSecurityContext="true" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:1805/MyWCFService/Service.svc"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IMyService"
contract="MyServiceReference.IMyService" name="WSHttpBinding_IMyService">
<identity>
<userPrincipalName value="manuba@wipro.com" />
</identity>
</endpoint>
</client>
</system.serviceModel>
</configuration>
Step 14.Run your client application
Run your windows application and clik on the button
So now you can see that the WCF is so simple :)
2009-06-16
Basics Of Windows Workflow Foundation
A set of activities that coordinate people
and / or software.
What are Activities?
An activity is a step or unit that represents runtime logic in a workflow.is the basic building block.An activity can expose properties and events that can be programmed againist within a workflow. An activity can also contain methods that are invoked by the workflow designer or workflowRuntime.
Properties and events that are exposed to the outside world and can be programmed from the workflow.It Supports pre/post interception hooks into execution in user code.
Methods which implement the inner behavior and are called by the workflow runtime.
What are the different categories of Activity?
Activites fall under two broad categories:
- Basic or sometimes called Primitive activities, which are steps in a workflow that execute runtime logic.Basic activities are steps that “do work”
- composite – which manage a set of child activities.In fact, a workflow itself is an activity.One variant of composite activites is a root activity.Workflows are just a special kind of composite activity
What are the different Types Of Workflow?
There are two types of workflow:
1.Sequential
2.State Machine
A state-based workflow waits on external entities to perform some action before moving on to the next step. On the other hand, a sequential workflow is just a continuous flow of operations which might include branching, but steps in the sequential workflow don't wait for an external entity to perform the operation, and then continue.
Which workflow to choose ?
Sequential workflow follows the traditional style of thinking - i.e. as long as the process is simple and stays in the boundary then a sequential workflow will work.
On the other hand, state machine workflows deal with different states of the workflow. A process which involves several different iterations before getting into the final shape is a candidate for being a state machine workflow.
Why Workflows and WF?
One of the biggest reasons for creating a workflow is that you are actually creating a model. Most of the business processes have some sort of model associated with them, whether it is use-cases, UML diagrams or a simple flow chart. In a process you always have some flow and thus, there will always be some steps involved in its execution.
With WF, model and workflow are one and the same. You use pieces of a business process to make a workflow and you piece together the workflow, which makes a model. Before WF you would make couple of UML diagrams, drawing flow-charts, writing pseudo code, explaining in bulleted text how an operation should work and then finally you will get to writing the code, whereas with WF when you are modeling the business process you are also building the application!
What is the Host Process for WF?
A WF has no executable environment and requires a host process within which it can execute. They are not applications themselves, rather, they require an application where they can reside. This host process can be a Windows Application or an ASP.NET Web application.
What is Workflow RunTime Engine?
The WF runtime engine executes workflow made up of activities created with VS2005 Workflow Designer. The runtime engine includes three basic services:
-1.Scheduling (schedules the execution of activities within a workflow)
-2.State Management (allows the state of the workflow to be persisted instead of storing it in some other mechanism like database)
-3.Rules (executes policy activities i.e., add rules on the workflow against certain activities in order to control the flow)
2009-06-15
Advantages of WCF over Webservice
- WCF has support for multiple protocols (TCP/IP, HTTP, PIPE, MSMQ etc.)
- WCF can be hosted outside if IIS ie: can be hosted in managed windows applications, a windows service, and WAS (Windows Process Activation Service)
- WCF provides customisation such as event hooks into service start / end / init / custom global error Handling etc. etc.
2009-06-12
C# 3.0 Tutorial -9:Linq To Entities
It is basically the replacement of L2S(Linq to SQL).
This guide should be a good starting point for anyone whether or not they are familiar with L2S, and a quick 'jumping guide' to L2S developers. Here's how to get started:
Step 1.Create a Database in your SQL Server
Open the Sql Server ,Right Click On the Database and click on the new Database.
In the "New Database" modal window ,put the name "MyDb" in "Database Name" textbox
Step 2.Create Tables in your Database
Create 2 feilds :
a)CustomerID- the datatype is int and it is an identity column and make it is as Primary Key
b)CustomerName-the data type is varchar(50)
Save the table is "Cust_Master"
Create another table Cust_Dtls(Contain CustomerID(int) and CustLocation(varchar(50)) as follows
Make a foreign Key relation between two table with CustomerID
Step 3.Create a new Website in Visual Studio
In your New Web Site Dialog box select ASP.NET Web Site nad Choose "Visual C#" in your Language Dropdown.
Type "L2EDemo" as your Web Site name and click OK.
Step 4.Create App_Code Folder within your solution
Step 5.Make your Ado.NET Entity Data Model
Right Click on your App_Code folder and click on "Add New Item..."
Choose "ADO.NET Entity Data Model" and name it (I left the default Model.edmx for the example)
Click on Add.
Click on Generate From Database
Click Next.
In the Entity Data Model Wizard Click on "New Connection"
Choose Microsoft SQL Server in your "Choose Data Source" Dialog Box
Choose The server Name and select your MyDb Database
Click OK and then Click on "Next"
Choose Cust_Dtls and Cust_Master tables
Then Click on Finish
Now your Model.edmx will be looked like as follows
Step 6.Access Your edmx
Go to your Default.aspx.cs Page
Include the namespace MyDbModel
using MyDbModel;
you will get the namespace from your ModelBrowser when the Model.edmx is opened
Step 7.Code for Save the record using L2E
protected void SaveRecord()
{
MyDbEntities db = new MyDbEntities();
Cust_Master cust = new Cust_Master();
cust.CustomerName = "Manab";
db.AddToCust_Master(cust);
db.SaveChanges();
}
Step 8.Code for modify records using L2E
MyDbEntities db = new MyDbEntities();
db.Cust_Master.First(c => c.CustomerID == 1).CustomerName = "Ranjan";
db.SaveChanges();
Step 9.Code to Display Records
MyDbEntities db = new MyDbEntities();
foreach (Cust_Master c in (from _c in db.Cust_Master select _c))
{
Response.Write("Customer ID : " + c.CustomerID);
Response.Write("<br/>");
Response.Write("Customer Name : " + c.CustomerName);
}
Step 10.Code To Delete Records
MyDbEntities db = new MyDbEntities();
db.DeleteObject(db.Cust_Master.First(c => c.CustomerID == 1));
db.SaveChanges();
Complete Code:
using System;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using MyDbModel;
public partial class _Default : System.Web.UI.Page
{
MyDbEntities db;
protected void Page_Load(object sender, EventArgs e)
{
}
protected void SaveRecord()
{
db = new MyDbEntities();
Cust_Master cust = new Cust_Master();
cust.CustomerName = "Manab";
db.AddToCust_Master(cust);
db.SaveChanges();
}
protected void ModifyRecord()
{
db = new MyDbEntities();
db.Cust_Master.First(c => c.CustomerID == 1).CustomerName = "Ranjan";
db.SaveChanges();
}
protected void showRecords()
{
db = new MyDbEntities();
foreach (Cust_Master c in (from _c in db.Cust_Master select _c))
{
Response.Write("Customer ID : " + c.CustomerID);
Response.Write("<br/>");
Response.Write("Customer Name : " + c.CustomerName);
}
}
protected void deleteRecord()
{
db = new MyDbEntities();
db.DeleteObject(db.Cust_Master.First(c => c.CustomerID == 1));
db.SaveChanges();
}
}
Now that should get you started. Like I said, if you are familiar with L2S, this transition should be no problem, and if you are new to this whole Linq arena, this should be simple to pick up. This new ADO is getting more and more impressive the more MS works on it. I can't even imagine going back to the old methods...
Related Resource:
C# 3.0 Tutorial -1:Var Keyword
C# 3.0 Tutorial -2:Extension Methods
C# 3.0 Tutorial -3:Lambda ExpressionsC# 3.0 Tutorial -4:Object Initializers
C# 3.0 Tutorial -5:Anonymous Types
C# 3.0 Tutorial -6:Type Equivalence
C# 3.0 Tutorial -7:Projections
C# 3.0 Tutorial -8:Linq
tags:Linq to Entities tutorials ,step by step Linq to Entities(L2E)
2009-06-03
C# 3.0 Tutorial -8:Linq
Introducing Linq
Linq is short for Language Integrated Query. If you are used to using SQL to query databases, you are going to have something of a head start with Linq, since they have many ideas in common. Before we dig into Linq itself, let's step back and look at what makes SQL different from C#.
Imagine we have a list of orders. For this example, we will imagine they are stored in memory, but they could be in a file on disk too. We want to get a list of the costs of all orders that were placed by the customer identified by the number 84. If we set about implementing this in C# before version 3 and a range of other popular languages, we would probably write something like (assuming C# syntax for familiarity):
List
foreach (Order o in Orders)
if (o.CustomerID == 84)
Found.Add(o.Cost);
Here we are describing how to achieve the result we want by breaking the task into a series of instructions. This approach, which is very familiar to us, is called imperative programming. It relies on us to pick a good algorithm and not make any mistakes in the implementation of it; for more complex tasks, the algorithm is more complex and our chances of implementing it correctly decrease.
If we had the orders stored in a table in a database and we used SQL to query it, we would write something like:
SELECT Cost FROM Orders WHERE CustomerID = 84
Here we have not specified an algorithm, or how to get the data. We have just declared what we want and left the computer to work out how to do it. This is known as declarative or logic programming.
Linq brings declarative programming features into imperative languages. It is not language specific, and has been implemented in the Orcas version of VB.Net amongst other languages. In this series we are focusing on C# 3.0, but the principles will carry over to other languages.
Understanding A Simple Linq Query
Let's jump straight into a code example. First, we'll create an Order class, then make a few instances of it in a List as our test data. With that done, we'll use Linq to get the costs of all orders for customer 84.
class Order
{
private int _OrderID;
private int _CustomerID;
private double _Cost;
public int OrderID
{
get { return _OrderID; }
set { _OrderID = value; }
}
public int CustomerID
{
get { return _CustomerID; }
set { _CustomerID = value; }
}
public double Cost
{
get { return _Cost; }
set { _Cost = value; }
}
}
class Program
{
static void Main(string[] args)
{
// Set up some test orders.
var Orders = new List
new Order {
OrderID = 1,
CustomerID = 84,
Cost = 159.12
},
new Order {
OrderID = 2,
CustomerID = 7,
Cost = 18.50
},
new Order {
OrderID = 3,
CustomerID = 84,
Cost = 2.89
}
};
// Linq query.
var Found = from o in Orders
where o.CustomerID == 84
select o.Cost;
// Display results.
foreach (var Result in Found)
Console.WriteLine("Cost: " + Result.ToString());
}
}
The output of running this program is:
Cost: 159.12
Cost: 2.89
Let's walk through the Main method. First, we use collection and object initializers to create a list of Order objects that we can run our query over. Next comes the query - the new bit. We declare the variable Found and request that its type be inferred for us by using the "var" keyword.
We then run across a new C# 3.0 keyword: "from".
from o in Orders
This is the keyword that always starts a query. You can read it a little bit like a "foreach": it takes a collection of some kind after the "in" keyword and makes what is to the left of the "in" keyword refer to a single element of the collection. Unlike "foreach", we do not have to write a type.
Following this is another new keyword: "where".
where o.CustomerID == 84
This introduces a filter, allowing us to pick only some of the objects from the Orders collection. The "from" made the identifier "o" refer to a single item from the collection, and we write the condition in terms of this. If you type this query into the IDE yourself, you will notice that it has worked out that "o" is an Order and intellisense works as expected.
The final new keyword is "select".
select o.CostThis comes at the end of the query and is a little like a "return" statement: it states what we want to appear in the collection holding the results of the query. As well as primitive types (such as int), you can instantiate any object you like here. In this case, we will end up with Found being a List
You may be thinking at this point, "hey, this looks like SQL but kind of backwards and twisted about a bit". That is a pretty good summary. I suspect many who have written a lot of SQL will find the "select comes last" a little grating at first; the other important thing to remember is that all of the conditions are to be expressed in C# syntax, not SQL syntax. That means "==" for equality testing, rather than "=" in SQL. Thankfully, in most cases that mistake will lead to a compile time error anyway.
A Few More Simple Queries
We may wish our query to return not only the Cost, but also the OrderID for each result that it finds. To do this we take advantage of anonymous types.
var Found = from o in Orders
where o.CustomerID == 84
select new { OrderID = o.OrderID, Cost = o.Cost };
Here we have defined an anonymous type that holds an OrderID and a Cost. This is where we start to see the power and flexibility that they offer; without them we would need to write custom classes for every possible set of results we wanted. Remembering the projection syntax, we can shorten this to:
var Found = from o in Orders
where o.CustomerID == 84
select new { o.OrderID, o.Cost };
And obtain the same result. Note that you can perform whatever computation you wish inside the anonymous type initializer. For example, we may wish to return the Cost of the order with an additional sales tax of 10% added on to it.
var Found = from o in Orders
where o.CustomerID == 84
select new {
o.OrderID,
o.Cost,
CostWithTax = o.Cost * 1.1
};
Conditions can be more complex too, and are built up in the usual C# way, just as you would do in an "if" statement. Here we apply an extra condition that we only want to see orders valued over a hundred pounds.
var Found = from o in Orders
where o.CustomerID == 84 && o.Cost > 100
select new {
o.OrderID,
o.Cost,
CostWithTax = o.Cost * 1.1
};
Ordering :
It is possible to sort the results based upon a field or the result of a computation involving one or more fields. This is achieved by using the new "orderby" keyword.
var Found = from o in Orders
where o.CustomerID == 84
orderby o.Cost ascending
select new { o.OrderID, o.Cost };
After the "orderby" keyword, we write the expression that the objects will be sorted on. In this case, it is a single field. Notice this is different from SQL, where there are two words: "ORDER BY". I have added the keyword "ascending" at the end, though this is actually the default. The result is that we now get the orders in order of increasing cost, cheapest to most expensive. To get most expensive first, we would have used the "descending" keyword.
While I said earlier that the ordering condition is based on fields in the objects involved in the query, it actually doesn't have to be. Here's a way to get the results in a random order.
Random R = new Random();
var Found = from o in Orders
where o.CustomerID == 84
orderby R.Next()
select new { OrderID = o.OrderID, Cost = o.Cost };
Joins
So far we have just had one type of objects to run our query over. However, real life is usually more complex than this. For this example, let's introduce another class named Customer.
class Customer
{
private int _CustomerID;
private string _Name;
private string _Email;
public int CustomerID
{
get { return _CustomerID; }
set { _CustomerID = value; }
}
public string Name
{
get { return _Name; }
set { _Name = value; }
}
public string Email
{
get { return _Email; }
set { _Email = value; }
}
}
In the Main method, we will also instantiate a handful of Customer objects and place them in a list.
var Customers = new List
new Customer {
CustomerID = 7,
Name = "Emma",
Email = "emz0r@worreva.com"
},
new Customer {
CustomerID = 84,
Name = "Pedro",
Email = "pedro@cerveza.es"
},
new Customer {
CustomerID = 102,
Name = "Vladimir",
Email = "vladimir@pivo.ru"
}
};
We would like to produce a list featuring all orders, stating the ID and cost of the order along with the name of the customer. To do this we need to involve both the List of orders and the List of customers in our query. This is achieved using the "join" keyword. Let's replace our query and output code with the following.
// Query.
var Found = from o in Orders
join c in Customers on o.CustomerID equals c.CustomerID
select new { c.Name, o.OrderID, o.Cost };
// Display results.
foreach (var Result in Found)
Console.WriteLine(Result.Name + " spent " +
Result.Cost.ToString() + " in order " +
Result.OrderID.ToString());The output of running this program is:
Pedro spent 159.12 in order 1
Emma spent 18.5 in order 2
Pedro spent 2.89 in order 3
We use the "join" keyword to indicate that we want to refer to another collection in our query. We then once again use the "in" keyword to declare an identifier that will refer to a single item in the collection; in this case it has been named "c". Finally, we need to specify how the two collections are related. This is achieved using the "on ... equals ..." syntax, where we name a field from each of the collections. In this case, we have stated that the CustomerID of an Order maps to the CustomerID of a Customer.
When the query is evaluated, an object in the Customers collection is located to match each object in the Orders collection. Note that if there were many customers with the same ID, there may be more than one matching Customer object per Order object. In this case, we get extra results. For example, change Vladimir to also have an OrderID of 84. The output of the program would then be:
Pedro spent 159.12 in order 1
Vladimir spent 159.12 in order 1
Emma spent 18.5 in order 2
Pedro spent 2.89 in order 3
Vladimir spent 2.89 in order 3
Notice that Vladimir never featured in the results before, since he had not ordered anything.
Getting All Permutations With Multiple "from"s
It is possible to write a query that gets every combination of the objects from two collections. This is achieved by using the "from" keyword multiple times.
var Found = from o in Orders
from c in Customers
select new { c.Name, o.OrderID, o.Cost };
Earlier I suggested that you could think of "from" as being a little bit like a "foreach". You can also think of multiple uses of "from" a bit like nested "foreach" loops; we are going to get every possible combination of the objects from the two collections. Therefore, the output will be:
Emma spent 159.12 in order 1
Pedro spent 159.12 in order 1
Vladimir spent 159.12 in order 1
Emma spent 18.5 in order 2
Pedro spent 18.5 in order 2
Vladimir spent 18.5 in order 2
Emma spent 2.89 in order 3
Pedro spent 2.89 in order 3
Vladimir spent 2.89 in order 3
Which is not especially useful. You may have spotted that you could have used "where" in conjunction with the two "from"s to get the same result as the join:
var Found = from o in Orders
from c in Customers
where o.CustomerID == c.CustomerID
select new { c.Name, o.OrderID, o.Cost };
However, don't do this, since it computes all of the possible combinations before the "where" clause, which goes on to throw most of them away. This is a waste of memory and computation. A join, on the other hand, never produces them in the first place.
Grouping
Another operations that you may wish to perform is categorizing objects that have the same value in a given field. For example, we might want to categorize orders by CustomerID. The result we expect back is a list of groups, where each group has a key (in this case, the CustomerID) and a list of matching objects. Here's the code to do the query and output the results.
// Group orders by customer.
var OrdersByCustomer = from o in Orders
group o by o.CustomerID;
// Iterate over the groups.
foreach (var Cust in OrdersByCustomer)
{
// About the customer...
Console.WriteLine("Customer with ID " + Cust.Key.ToString() +
" ordered " + Cust.Count().ToString() + " items.");
// And what they ordered.
foreach (var Item in Cust)
Console.WriteLine(" ID: " + Item.OrderID.ToString() +
" Cost: " + Item.Cost.ToString());
}
The output that it produces is as follows:
Customer with ID 84 ordered 2 items.
ID: 1 Cost: 159.12
ID: 3 Cost: 2.89
Customer with ID 7 ordered 1 items.
ID: 2 Cost: 18.5
This query looks somewhat different to the others that we have seen so far in that it does not end with a "select". The first line is the same as we're used to. The second introduces the new "group" and "by" keywords. After the "by" we name the field that we are going to group the objects by. Before the "by" we put what we would like to see in the resulting per-group collections. In this case, we write "o" so as to get the entire object. If we had only been interested in the Cost field, however, we could have written:
// Group orders by customer.
var OrdersByCustomer = from o in Orders
group o.Cost by o.CustomerID;
// Iterate over the groups.
foreach (var Cust in OrdersByCustomer)
{
// About the customer...
Console.WriteLine("Customer with ID " + Cust.Key.ToString() +
" ordered " + Cust.Count().ToString() + " items.");
// And the costs of what they ordered.
foreach (var Cost in Cust)
Console.WriteLine(" Cost: " + Cost.ToString());
}Which produces the output:
Customer with ID 84 ordered 2 items.
Cost: 159.12
Cost: 2.89
Customer with ID 7 ordered 1 items.
Cost: 18.5
You are not restricted to just a single field or the object itself; you could, for example, instantiate an anonymous type there instead.
Query Continuations
At this point you might be wondering if you can follow a "group ... by ..." with a "select". The answer is yes, but not directly. Both "group ... by ..." and "select" are special in so far as they produce a result. You must terminate a Linq query with one or the other. If you try to do something like:
var CheapOrders = from o in Orders
where o.Cost < ordercounts =" from" customerid =" g.Key," totalorders =" g.Count()">
Code Snippet (in ASPX Page)
using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Collections.Generic;
public partial class CSharp3_Linq : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
var Orders = new List<Order>
{
new Order{OrderID=1,CustomerID=84,Cost=159.12},
new Order{OrderID=2,CustomerID=7,Cost=18.50},
new Order{OrderID=3,CustomerID=84,Cost=2.89},
};
var Customers = new List<CustomerDescription>
{
new CustomerDescription{CustomerID=7,Name="Manab",Email="manab@wipro.com"},
new CustomerDescription{CustomerID=84,Name="Indra",Email="indra@wipro.com"},
new CustomerDescription{CustomerID=102,Name="Arun",Email="arun@wipro.com"}
};
//Simple LINQ Query-to get the costs of all orders for customer 84.
var Found1 = from o in Orders
where o.CustomerID == 84
select o.Cost;
foreach (var Result in Found1)
Response.Write("Found 1->Cost: " + Result.ToString()+"<br/>");
//query to return not only the Cost, but also the OrderID for each result that it finds
var Found2 = from o in Orders
where o.CustomerID == 84
select new { MyOrderID = o.OrderID, MyCost = o.Cost };
foreach (var Result in Found2)
Response.Write("Found 2->Cost: " + Result.MyCost.ToString() +" Order ID:" + Result.MyOrderID.ToString() + "<br/>");
//with the projection syntax, we can shorten this to:
var Found3 = from o in Orders
where o.CustomerID == 84
select new { o.OrderID, o.Cost };
foreach (var Result in Found3)
Response.Write("Found 3->Cost: " + Result.Cost.ToString() + " Order ID:" + Result.OrderID.ToString() + "<br/>");
//return the Cost of the order with an additional sales tax of 10% added on to it.
var Found4 = from o in Orders
where o.CustomerID == 84
select new
{
o.OrderID,
o.Cost,
CostWithTax = o.Cost * 1.1
};
foreach (var Result in Found4)
Response.Write("Found 4->Cost: " + Result.Cost.ToString() + " Order ID:" + Result.OrderID.ToString() +" Cost with Tax:"+ Result.CostWithTax.ToString()+ "<br/>");
//apply an extra condition that we only want to see orders valued over a hundred pounds.
var Found5 = from o in Orders
where o.CustomerID == 84 && o.Cost > 100
select new
{
o.OrderID,
o.Cost,
CostWithTax = o.Cost * 1.1
};
foreach (var Result in Found5)
Response.Write("Found 5->Cost: " + Result.Cost.ToString() + " Order ID:" + Result.OrderID.ToString() + " Cost with Tax:" + Result.CostWithTax.ToString() + "<br/>");
//Order By Clause
var Found6 = from o in Orders
where o.CustomerID == 84
orderby o.Cost ascending
select new { o.OrderID, o.Cost };
foreach (var Result in Found6)
Response.Write("Found 6->Cost: " + Result.Cost.ToString() + " Order ID:" + Result.OrderID.ToString() + "<br/>");
//get the results in a random order
Random R = new Random();
var Found7 = from o in Orders
where o.CustomerID == 84
orderby R.Next()
select new { OrderID = o.OrderID, Cost = o.Cost };
foreach (var Result in Found7)
Response.Write("Found 7->Cost: " + Result.Cost.ToString() + " Order ID:" + Result.OrderID.ToString() + "<br/>");
//Joining
var Found8 = from o in Orders
join c in Customers on o.CustomerID equals c.CustomerID
select new { c.Name, o.OrderID, o.Cost };
foreach (var Result in Found8)
Response.Write("Found 8->" +Result.Name + " spent " + Result.Cost.ToString() + " in order " +Result.OrderID.ToString()+"<br/>");
//Joining with multiple from
var Found9 = from o in Orders
from c in Customers
where o.CustomerID==c.CustomerID
select new { c.Name, o.OrderID, o.Cost };
foreach (var Result in Found9)
Response.Write("Found 9->" + Result.Name + " spent " + Result.Cost.ToString() + " in order " + Result.OrderID.ToString() + "<br/>");
//Group By
var OrdersByCustomer = from o in Orders
group o by o.CustomerID;
foreach (var Cust in OrdersByCustomer)
{
// About the customer...
Response.Write("Customer with ID " + Cust.Key.ToString() +
" ordered " + Cust.Count().ToString() + " items.<br/>");
// And what they ordered.
foreach (var Item in Cust)
Response.Write(" ID: " + Item.OrderID.ToString() +
" Cost: " + Item.Cost.ToString()+"<br/>");
}
}
}
class Order
{
private int _OrderID;
private int _CustomerID;
private double _Cost;
public int OrderID
{
get { return _OrderID; }
set { _OrderID = value; }
}
public int CustomerID
{
get { return _CustomerID; }
set { _CustomerID = value; }
}
public double Cost
{
get { return _Cost; }
set { _Cost = value; }
}
}
class CustomerDescription
{
private int _CustomerID;
private string _Name;
private string _Email;
public int CustomerID
{
get { return _CustomerID; }
set { _CustomerID = value; }
}
public string Name
{
get { return _Name; }
set { _Name = value; }
}
public string Email
{
get { return _Email; }
set { _Email = value; }
}
}
Output :
Found 1->Cost: 159.12
Found 1->Cost: 2.89
Found 2->Cost: 159.12 Order ID:1
Found 2->Cost: 2.89 Order ID:3
Found 3->Cost: 159.12 Order ID:1
Found 3->Cost: 2.89 Order ID:3
Found 4->Cost: 159.12 Order ID:1 Cost with Tax:175.032
Found 4->Cost: 2.89 Order ID:3 Cost with Tax:3.179
Found 5->Cost: 159.12 Order ID:1 Cost with Tax:175.032
Found 6->Cost: 2.89 Order ID:3
Found 6->Cost: 159.12 Order ID:1
Found 7->Cost: 159.12 Order ID:1
Found 7->Cost: 2.89 Order ID:3
Found 8->Indra spent 159.12 in order 1
Found 8->Manab spent 18.5 in order 2
Found 8->Indra spent 2.89 in order 3
Found 9->Indra spent 159.12 in order 1
Found 9->Manab spent 18.5 in order 2
Found 9->Indra spent 2.89 in order 3
Customer with ID 84 ordered 2 items.
ID: 1 Cost: 159.12
ID: 3 Cost: 2.89
Customer with ID 7 ordered 1 items.
ID: 2 Cost: 18.5
Under The Hood
Now we have looked at the practicalities of using Linq, I am going to spend a little time taking a look at how it works. Don't worry if you don't understand everything in this section, it's here for those who like to dig a little deeper.
Throughout the series I have talked about how all of the language features introduced in C# 3.0 somehow help to make Linq possible. While anonymous types have shown up pretty explicitly and you can see from the lack of type annotations we have been writing that there is some type inference going on, where are the extension methods and lambda expressions?
There's a principle in language design and implementation called "syntactic sugar". We use this to describe cases where certain syntax isn't directly compiled, but is first transformed into some other more primitive syntax and then passed to the compiler. This is exactly what happens with Linq: your queries are transformed into a sequence of method calls and lambda expressions.
The C# 3.0 specification goes into great detail about these transformations. In practice, you probably don't need to know about this, but let's look at one example to help us understand what is going on. Our simple query from earlier:
var Found = from o in Orders
where o.CustomerID == 84
select o.Cost;After transformation by the compiler, becomes:
var Found = Orders.Where(o => o.CustomerID == 84)
.Select(o => o.Cost);
And this is what actually gets compiled. Here the use of lambda expressions becomes clear. The lambda passed to the Where method is called on each element of Orders to determine whether it should be in the result or not. This produces another intermediate collection, which we then call the Select method on. This calls the lambda it is passed on each object and builds up a final collection of the results, which is then assigned to Found. Beautiful, huh?
Finally, a note on extension methods. Both Where and Select, along with a range of other methods, have been implemented as extension methods. The type they use for "this" is IEnumerable, meaning that any collection that implements that interface can be used with Linq. Without extension methods, it would not have been possible to achieve this level of code re-use.
DLinq and XLinq
In this article I have demonstrated Linq working with objects instantiated from classes that we implemented ourselves and stored in built-in collection classes that implement IEnumerable. However, the query syntax compiles down to calls on extension methods. This means that it is possible to write alternative implementations of Linq that follow the same syntax but perform different operations.
Two examples of this, which will ship with C# 3.0, are DLinq and XLinq. DLinq enables the same language integrated query syntax to do queries on databases by translating the Linq into SQL. XLinq enables queries on XML documents.
Conclusion
Linq brings declarative programming to the C# language and will refine and unify the way that we work with objects, databases, XML and whatever anyone else writes the appropriate extension methods for. It builds upon the language features that we have already seen in the previous parts of the series, but hiding some of them away under syntactic sugar. While the query language has a range of differences to SQL, there are enough similarities to make knowledge of SQL useful to those who know it. However, its utility is far beyond providing yet another way to work with databases.
Closing Thoughts On C# 3.0
This brings us to the end of this four part series on C# 3.0. Here is a quick recap on all that we have seen.
Type inference removes much of the tedium of writing out type annotations again and again.
Lambda expressions make higher order programming syntactically light.
Extension methods provide another path to better code re-use when correctly applied.
Object and collection initializers along with anonymous types make building up large data structures much less effort.
Linq gives us declarative programming abilities over objects, databases and XML documents.
When I saw C# 1.0 I highly doubted that C# was going to be a language I would ever be excited about. I have been pleasantly surprised, and writing this series has been a lot of fun. I hope that it has been informative and enjoyable to read, and that it will help you to make powerful use of the new language features. I greatly look forward to being able to use them in my own day-to-day development and seeing how other people use them.
Of course, knowing about something and doing it yourself are two entirely different things; if you haven't already done so, grab yourself the Visual Studio 2008 trial or the free Express Edition. Only then will you become comfortable with the new features and be able to use them effectively in your own development. Happy hacking, and have fun!
Reference:www.programmersheaven.com
tags:what is LINQ,step by step tutorials of Linq,what is new in c# 3.0/3.5,beginner tutorials on Linq
C# 3.0 Tutorial -7:Projections
There is one final feature of anonymous types to point out, and until you see Linq this is going to feel a little obscure. So far we have declared a field in an anonymous type by specifying its name and initializing it to a value. There are two other ways.
The first is to simply write the name of an already declared variable. The name of the variable will be taken as the name of the field, and the value it holds will be used to initialize the field. Using this, you could rewrite:
var x = new {
Real = 5.4,
Complex = 2.8
};As:
var Real = 5.4;
var Complex = 2.8;
var x = new {
Real,
Complex
};
In this case it complicates the code, but it's worth being aware of. There is a variation on this where instead of naming a variable, you access a member of an existing object. The field takes the name and value of the member.
Imagine we have a class called Customer that represents all of the details of a customer, but we just want an anonymous type that contains the name and email address. We can write the following:
Customer c = GetCustomer(1764);
var EmailRecord = new { c.Name, c.Email };This is equivalent to:
Customer c = GetCustomer(1764);
var EmailRecord = new {
Name = c.Name,
Email = c.Email
};
tags:what is projections in c# 3.0 /3.5
C# 3.0 Tutorial -6:Type Equivalence
Type equivalence involves determining if two values are of the same type. In this case, we are concerned with type equivalence of objects instantiated from anonymous classes.
This comes up in practice when assignment is considered. Let's take an example.
var x = new {
Real = 5.4,
Complex = 2.8
};
var y = new {
Real = 1.9,
Complex = 5.3
};
x = y;Remember from the first part of the series that C# 3.0 is statically typed. That means that the variables x and y both have and retain a given type. Therefore, if the assignment is to work then y has to be of the same type as x (we don't have to consider subtyping here, since anonymous classes always inherit from object).
Two anonymous types will be considered equivalent if all of the following properties are true:
They have the same number of fields
They have fields of the same name declared in the same order
The types of each of the fields are identical
In the previous example, this is the case. However, any of the following changes to the anonymous type that was instantiated to give y will result in the types not being equivalent and the assignment resulting in a compile time error.
// Not equivalent due to an extra field.
var y = new {
Real = 1.9,
Complex = 5.3,
Conjugated = -5.3
};
// Not equivalent - fields in a different order.
var y = new {
Complex = 5.3,
Real = 1.9
};
// Not equivalent; different types (int != double)
var y = new {
Complex = 4,
Real = 2
};
Code Snippet(Aspx page)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class CSharp3_TypeEquivalance : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
//Type Equivalance
var x = new { Real = 4.5, Complex = 2.8 };
//Not equivalent due to an extra field
var y1 = new { Real = 4.6, complex = 2.9, id = "123" };
//Not equivalent - fields in a different order
var y2 = new { Complex = 5.3,Real = 1.9};
// Not equivalent; different types (int != double)
var y3 = new{Complex = 4,Real = 2};
//have the same number of fields ,have fields of the same name declared in the same order ,The types of each of the fields are identical
var y4 = new { Real = 1.9, Complex = 5.3 };
Response.Write("x.GetType() == y1.GetType() :" + ((x.GetType() == y1.GetType()) ? "Yes" : "No,Not equivalent due to an extra field"));
Response.Write("<br/>");
Response.Write("x.GetType() == y2.GetType() :" + ((x.GetType() == y2.GetType()) ? "Yes" : "No,Not equivalent - fields in a different order"));
Response.Write("<br/>");
Response.Write("x.GetType() == y3.GetType() :" + ((x.GetType() == y3.GetType()) ? "Yes" : "No,Not equivalent; different types (int != double)"));
Response.Write("<br/>");
Response.Write("x.GetType() == y4.GetType() :" + ((x.GetType() == y4.GetType()) ? "Yes,have the same number of fields ,have fields of the same name declared in the same order ,The types of each of the fields are identical " : "No"));
Response.Write("<br/>");
if (x.GetType() == y1.GetType())
{
Response.Write("<br/>");
Response.Write(x.Real);
}
}
}
Output :
x.GetType() == y1.GetType() :No,Not equivalent due to an extra field
x.GetType() == y2.GetType() :No,Not equivalent - fields in a different order
x.GetType() == y3.GetType() :No,Not equivalent; different types (int != double)
x.GetType() == y4.GetType() :Yes,have the same number of fields ,have fields of the same name declared in the same order ,The types of each of the fields are identical
tags:what is Type Equivalence in 3.0/3.5,how can I implement Type Equivalence in c# 3.0/3.5
C# 3.0 Tutorial -5:Anonymous Types
Anonymous simply means "without a name", and you can safely read the word "type" as "class" in this case. That is, in this section we are going to discuss the idea of classes without names.
In C# 2.0 we saw the introduction of anonymous methods. One of the consequences of a method having no name is that we had to take a reference to it - stored in a delegate type - right away, so we had some way to refer to it. The analogy with anonymous classes is that we are required to instantiate them right away. Therefore, the construct for creating an anonymous class also instantiates that class.
In C# 3.0, anonymous classes are greatly limited compared to standard classes. They can only inherit from object and their only memebers are private fields each with a matching read/write property.
With all of these things in mind, let's see how we declare and instantiate an anonymous type.
var MyProduct = new {
Name = "Vacuum Cleaner",
Price = 94.99,
Description = "Really sucks! Have your carpets clean in no time."
};
There are a couple of things to notice here. First is that we do not have a name for the class. Therefore, there is no type that we can write before the name of the variable when declaring it. What we can do, however, is to write "var", which leaves the compiler to work out the type for us. While the types are anonymous as far as we should care, the compiler and runtime actually do have some way of identifying them.
The second thing to notice is that we have used the "new" keyword but without specifying a type name. Instead, we have placed something after it that looks just like the object initializers we were looking at a few moments ago. This is not a co-incidence: we actually are initializing the object created by new. The question is, where is the definition of the class?
The class is created by looking at the initializer. For each name assigned to inside the initializer (Name, Price and Description in this case), a private field is created along with a get/set property. In this case, the class might look like this:
class __NO_NAME__ {
private string _Name;
private double _Price;
private string _Description;
public string Name {
get { return _Name; }
set { _Name = value; }
}
public double Price {
get { return _Price; }
set { _Price = value; }
}
public string Description {
get { return _Description; }
set { _Description = value; }
}
}
Note that the types of the fields are worked out by looking at what is being assigned to the property. Therefore, you are not allowed to assign a null value. It is the same type inference process that we have seen time and time again in C# 3.0.
Since anonymous classes are just classes and instances of them are just objects, you can do all of the things you'd expect to be able to with them, from simple things like accessing their properties through to more complicated things such as reflection.
Code Snippet(Aspx page)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class CSharp3_AnonymousType : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
//Anonymous Types
//Its look likes a class which have three following property
//it is read only property ,we can not change the value further
var MyProduct = new { CustName = "Manab", CustID = 100450, Location = "Kolkata" };
Response.Write("<br/>");
Response.Write("Cust Name : " + MyProduct.CustName + " Cust ID:" + MyProduct.CustID);
}
}
Output:
Cust Name : Manab Cust ID:100450
tags:what is Anonymous Types in c# 3.0/3.5,new features in c# 3.0/3.5,how can we implement anonymous types in c# 3.0/3.5