SQL Server knowledge center

everything about SQL Server
See also: Other Geeks@INDC

November 2007 - Posts

Going deeper with LINQ to XML Operations

Going deeper with LINQ to XML Operations

By : Kasim Wirama, MCDBA, MVP SQL Server

This article will discuss about classes in LINQ for XML. What is goal behind the creation API (separate DLL) LINQ for XML.

At the beginning, I thought that LINQ for XML API is created for accessing XML content with LINQ way. Later, my thought is incorrect. In fact, LINQ for XML API is independent from LINQ for XML. It means, you use LINQ for XML API to managing XML content whether you query with LINQ or not. Creation of this API is based on W3C standard XML infoset (http://www.w3.org/TR/xml-infoset).

What is infoset actually? Infoset is a set of information that specifies the structures of well-formed XML. What is well-formed XML in my understanding? As far as I know, well-formed XML has opening and closing tag, and each element has opening and closing tag inside their element container.

Goal creation of this API is to provide object oriented way of working with XML rather than document manipulation way with DOM. As element(s) has siblings and parents, it becomes good candidate for LINQ to come into XML stuff. Classes under this API are prefixed with X.

This API exists in System.Xml.Linq assembly with same namespace, so you need to add it as reference in your solution.

It seems there are some new ways of expressing LINQ to XML.

My Exploration

You can generate your XML into memory dynamically or loading from XML file, as sample below shown

XElement element = new XElement("Order",
new XElement("orderid","001"),
new XElement("quantity",10),
new XElement("price",50)
);

It will display

<Order>
<orderid>001</orderid>
<quantity>10</quantity>
<price>50</price>
</Order>

 

You can also calculate value among elements, for example calculating total amount in one order as below :

decimal totalPrice = (int)element.Element("quantity") * (decimal)element.Element("price");

It returns result 500

You need to implement namespace into XML. Namespace is useful in various scenario, one of them is to validate XML content against XML schema. XML namespace is declared in XNamespace class, as below :

XNamespace ns = "http://www.test.com/Customers";

And put namespace inside the XML element content like below :

XElement customers = new XElement (
ns+"customers",
new XElement(ns + "customer",
new XAttribute("firstname", "john"),
new XAttribute("lastname", "grisham")
),
new XElement(ns + "customer",
new XAttribute("firstname", "alex"),
new XAttribute("lastname", "good")
)
);

 

It will display output :

<customers xmlns="http://www.test.com/Customers">
<customer firstname="john" lastname="grisham" />
<customer firstname="alex" lastname="good" />
</customers>

 

You can add alias for XML namespace to the content.

XElement customers = new XElement (
ns+"customers",
new XAttribute(XNamespace.Xmlns+"c" , ns),
new XElement(ns + "customer",
new XAttribute("firstname", "john"),
new XAttribute("lastname", "grisham")),
new XElement(ns + "customer",
new XAttribute("firstname", "alex"),
new XAttribute("lastname", "good")
)
);

It will display the following result :

<c:customers xmlns:c="http://www.test.com/Customers">
<c:customer firstname="john" lastname="grisham" />
<c:customer firstname="alex" lastname="good" />
</c:customers>

 

Other useful class is Annotation. For XML, annotation is more like attribute in a class.
You can create a class as below :

public class CustomerNote
{
public string Notes;
}

Then you can create instance of CustomerNote and add it to XElement instance, later then you can retrieve back the annotation object and extract its property to display to the screen, see below code:

CustomerNote note = new CustomerNote { Notes = "just dummy notes" };
customers.AddAnnotation(note);
///retrieve back the object and extract value from its property
Console.WriteLine(customers.Annotation<CustomerNote>().Notes);

You can change XML element for example replace a element with its content, or change its element/attribute value with method ReplaceWith, SetAttributeValue, and SetElementValue. Feel free to see the content after change with Console.WriteLine(customers); here is the sample of ReplaceWith method

Sample of ReplaceWith method :

customers.LastNode.ReplaceWith(new XElement(ns+"customer",
new XAttribute("firstname","alexander"),
new XAttribute("lastname","good"),"Alexander"));

You can output the result into XML form from collection type object, for example :

public enum Countries{
USA,
Indonesia
}

public class Customer
{
public Countries Country;
public string Name;
public string City;
}

 

Then in Main static method of client console program, you create array of customers:

Customer[] customers = {
new Customer{ City="Jakarta", Country=Countries.Indonesia, Name="Anton"},
new Customer{ City="Bali", Country=Countries.Indonesia, Name="Budi"},
new Customer{ City="Wichita", Country=Countries.USA, Name="Inga"},
new Customer{ City="New York", Country=Countries.USA, Name="John"},
new Customer{ City="Florence", Country=Countries.USA, Name="George"}
};

var result =
new XElement("customers",
from c in customers
where c.Country == Countries.Indonesia
select new XElement(
new XElement("customer"
, new XAttribute("city",c.City)
, c.Name
)
)
);

 

The output is :

<customers>
<customer city="Jakarta">Anton</customer>
<customer city="Bali">Budi</customer>
</customers>

You can also query from xml file with LINQ, here the XML content structure :

<?xml version="1.0" encoding="utf-8" ?>
<customers>
<customer name="..." city="..." country="...." />
<customer name="..." city="..." country="...." />
.........
</customers>

XElement element = XElement.Load(@"c:\mycustomer.xml");

var result = from item in element.Elements("customer")
                where (string)item.Attribute("country") == "Indonesia"
                orderby (string)item.Attribute("name")
                select new
                {
                                Name = (string)item.Attribute("name"),
                                City = (string)item.Attribute("city") 
                };

The return type is IEnumerable<XElement>

You can also do querying between XML and object like this query below :

var result = from item in element.Elements("customer")
join o in orders
on (string)item.Attribute("Name") equals o.CustomerName
orderby (string)item.Attribute("Name")
select new
{
Name = (string)item.Attribute("Name"),
City = (string)item.Attribute("City"),
IdProduct = o.IdProduct,
Quantity = o.Quantity
};

Before you try above example, try to make dummy class Orders and array instance of order like this code below :

public class Order
{
public int OrderID;
public string CustomerName;
public int Quantity;
public int IdProduct;
}

And this one:

Order[] orders = {
new Order{ IdProduct=1, CustomerName="....", OrderID = 1, Quantity=10},
new Order{ IdProduct=2, CustomerName="....", OrderID = 2, Quantity=20}
};

You can replace repetitive explicit casting as you can see in (string)item.Attribute("Name") and (string)item.Attribute("City") with alias for each of them, so the query can be written as below:

var result = from item in element.Elements("customer")
let xName = (string)item.Attribute("name")
let xCity = (string)item.Attribute("city")
join o in orders
on xName equals o.CustomerName
orderby xName
select new
{
Name = xName,
City = xCity,
IdProduct = o.IdProduct,
Quantity = o.Quantity
};

In XML transformation with XSL, LINQ to XML also work with System.Xml.Xsl.XslCompiledTranform class to do transformation. XslCompiledTransform requires XPathNavigator class that exists in System.Xml.XPath. You can get the navigator instance from extension method CreateNavigator either from XmlDocument, XDocument or XElement. Here is the example.

XElement customers = XElement.Load(@"c:\mycustomer.xml");
XslCompiledTransform xslt = new XslCompiledTransform();
xslt.Load(@"c:\myxslt.xslt");xslt.Transform(customers.CreateNavigator(), null, Console.Out);

You can create XSLT from any XML tool including Visual Studio. With XPath, you can also do filtering with extension method XPathEvaluate.

For example, filtering only customer from Indonesia.

XElement result = new XElement(
"customers",
from c in customers
select new XElement
(
"customer",
new XAttribute("name", c.Name),
new XAttribute("city", c.City),
new XAttribute("country", c.Country)
)
);

Console.WriteLine(result.ToString());
Console.WriteLine();

var filter = (IEnumerable<object>)result.XPathEvaluate("/customer[@country='Italy']/@name");
foreach (var item in filter)
{
Console.WriteLine(item);
}

Because XPathEvaluate return object, you need to do explicit cast to IEnumerable<object>.

Other method is XPathSelectElement and XPathSelectElements, XPathSelectElement only return XElement type, whereas XPathSelectElements return IEnumerable<XElement>, so you can filter on XML nodes that returning IEnumerable<XElement> and you can join to IEnumerable<object> to return desired result. Here is the example :

XElement customers = XElement.Load(@"c:\mycustomer.xml");
var result = from c in customers.XPathSelectElements("/customer[@country='Indonesia']")
                let xName = (string)c.Attribute("name")
                let xCity = (string)c.Attribute("city")
                let xCountry = (string)c.Attribute("country")
                join o in orders
                on xName equals o.CustomerName
                orderby xName
                select new
                {
                                Name = xName,
                                City = xCity,
                                Country = xCountry,
                                IdProduct = o.IdProduct,
                                Quantity = o.Quantity
                };

foreach (var item in result)
{
                Console.WriteLine(item);
}

Share this post: | | | |
Posted: Nov 30 2007, 12:57 PM by Kasim.Wirama | with 2 comment(s)
Filed under:
Introduction Using LINQ in XML

Introduction Using LINQ in XML

By : Kasim Wirama, MCDBA, MVP SQL Server

This article, I would begin to explore LINQ implementation in XML. .NET framework 3.5 provide API dll for LINQ to XML through System.Xml.Linq, so include this into project reference, and also add it as namespace.

Most commonly used classes under System.Xml.Linq are XDocument, XDeclaration, XElement, and XAttributes.

These classes above has corresponding classes in DOM class, but classes under LINQ is much more simpler as long as you make your code formatting clear.

For example, assume there is XML structure as shown below

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

<contact id="001>

  <firstName>Johan</firstName>

  <lastName>Santoso</lastName>

  <addresses>

                <address type="home">

                                <addressItem ownership="rent">Sudirman St no. 2</addressItem>

                                <addressItem ownership="buy">Orchad Rd no. 3</addressItem>

                </address>

                <address type="apartment">

                                <addressItem ownership="buy">Thumb St 4</addressItem>

                </address>

  </addresses>

</contact>

I can write code to achieve the XML above as :

XDocument doc = new XDocument(

    new XDeclaration("1.0","utf-8","yes"),
        new XElement("contact", new XAttribute("id","001"),
            new XElement("firstname","Johan"),
            new XElement("lastname","Santoso"),
            new XElement("addresses",
                new XElement("address", new XAttribute("type","home"),
                    new XElement("addressItem",new XAttribute("ownership","rent"),"Sudirman St no.2"),
                    new XElement("addressItem", new XAttribute("ownership", "buy"), "Orchad Rd no. 3")
                    ),
                new XElement("address", new XAttribute("type","apartment"), 
                   new XElement("addressItem", new XAttribute("ownership", "buy"), "Thumb St 4")
                                                  )
                )
            )
    );

Try experimenting by yourself, and you will know how easy to generate XML structure with LINQ rather than using DOM. This single statement above is called functional construction.You can display the XML output to console window by calling ToString method on instace of XDocument.For querying with LINQ, I begin the most simple one as warming up. On next subsequent articles, I will go deeper about LINQ querying capability in XML. You can get list of addresses by getting descendants of Address element as code shown belowforeach(XElement child in doc.Descendants("address").Elements()){    Console.WriteLine(child);}It will return result :<addressItem ownership="rent">Sudirman St no. 2</addressItem>
<addressItem ownership="buy">Orchad Rd no. 3</addressItem>
<addressItem ownership="buy">Thumb St 4</addressItem>

You can try to set descendants to addresses, and see what results it will return.

Share this post: | | | |
Posted: Nov 30 2007, 12:44 PM by Kasim.Wirama | with no comments
Filed under:
Querying Dataset with LINQ

Querying Dataset with LINQ

By : Kasim Wirama, MCDBA, MVP SQL Server

 

This article, I would like to show how to access ADO.NET dataset and datatable using LINQ. System.Data.Dataset is a in-memory representation of a set of data. It has relational objects such as table, relationship among tables and constraint. So it is good candidate to be accessible by LINQ.

 

Querying data between datacontext and ADO.NET is a bit different. I would say there is stuff besides LINQ to SQL, i.e LINQ to Dataset (ADO.NET). In LINQ to Dataset, datatable doesn’t implement IEnumerable<T>, so you need call method AsEnumerable on the datatable to wrap it. Each member inside enumerable is datarow type. To access the column inside datarow, you can use Field<T> instead of direct cast as you usually do in previous .NET 3.5/C# 3.0.

 

Here is the example:

 class Class1{   
private const string connstring = "database=northwind;trusted_connection=yes;";   
private const string query = @"
select orderid, orderdate, freight, shipname,       
         
shipaddress, shipcity, shipcountry
        
          from orders        where customerid = @customerid;       
         
select od.orderid, od.unitprice, od.quantity, od.discount,
        
          p.[productName]
        
         
from [order details] od
        
         
inner join  orders o
        on o.orderid = od.orderid        
         
left join products p
        on p.productid = od.productid        
         
where o.customerid = @customerid;";
      public static void Main()   
{        
         
DataSet ds = LoadData();        
         
DataTable orders = ds.Tables["orders"];
        
         
DataTable orderdetails = ds.Tables["orderdetails"];
         
         
var query1 = from o in orders.AsEnumerable()                    
                   
join od in orderdetails.AsEnumerable()
                    
                   
on o.Field<int>("orderid") equals od.Field<int>("orderid")
                    
                   
into temptable
                    
                   
where o.Field<DateTime>("orderdate").Year >= 1998
                    
                   
orderby o.Field<DateTime>("orderdate") descending
                    
                   
select new { OrderID = o.Field<int>("orderid"),
                                
                                       
OrderDate = o.Field<DateTime>("orderdate"),
                                
                                       
Amount = temptable.Sum( od => od.Field<decimal>("unitprice") * od.Field<short>("quantity"))};
    
}

public static DataSet LoadData()
{    
         
DataSet ds = new DataSet("custorders");
    
         
SqlDataAdapter da = new SqlDataAdapter(query, connstring);
    
         
da.SelectCommand.Parameters.AddWithValue("@customerid", "QUICK");
    
         
da.TableMappings.Add("Table", "orders");
    
         
da.TableMappings.Add("Table1", "orderdetails");
    
         
da.Fill(ds);
    
         
return ds;
}
} 

 

If you define datable relationship among one another, you can call method GetChildRow from parent table to access child table, see this example below

 

 

 class Class1{    
          private const string connstring = …      

         
public static void Main()
    
          {
        
          DataSet ds = LoadData();        
         
DataTable orders = ds.Tables["orders"];
        
         
DataTable orderdetails = ds.Tables["orderdetails"];
        
         
ds.Relations.Add("Order_Orderdetails", orders.Columns["orderid"],
  orderdetails.Columns["orderid"]);         
         
var query3 = from o in orders.AsEnumerable()
                    
                                       
where o.Field<DateTime>("orderdate").Year >= 1998
                    
                                       
orderby o.Field<DateTime>("orderdate") descending
                    
                                       
select new { OrderID = o.Field<int>("orderid"),
                                 
                                                                              
OrderDate = o.Field<DateTime>("orderdate"),
                                 
                                                                              
TotalAmount = o.GetChildRows("Order_Orderdetails").Sum
                                                                                                              (x=>x.Field<decimal>("unitprice") * x.Field<short>("quantity"))
                                                          };
     

}

public static DataSet LoadData(){    }
} 

 

You can also modify value of a cell without existing mandatory to build query expression. For modification, you call method SetField<T>, as example shown below:

 

foreach (DataRow r in orderdetails.Rows)       
{            
             decimal before = r.Field<decimal>("unitprice");            
           
if (r.Field<decimal>("unitprice") < 10)
            
           
{
                
                       
r.SetField<decimal>("unitprice", 10);
                
                       
Console.WriteLine(r.Field<int>("orderid"));
                
                       
Console.WriteLine("before : " + before);
                
                       
Console.WriteLine("after  : " + r.Field<decimal>("unitprice"));
                
                       
Console.WriteLine();
            
           
}
       

}

 

Share this post: | | | |
Posted: Nov 29 2007, 11:47 PM by Kasim.Wirama | with 2 comment(s)
Filed under:
Execute Stored Procedure and Function from LINQ

Execute Stored Procedure and Function from LINQ

By : Kasim Wirama, MCDBA, MVP SQL Server

 

In this article I would like to show you how to call stored procedure, scalar function, and table value function from LINQ.

 

For these three kinds database object, they are hosted under DataContext derived class with attribute Function, to differentiate between function and stored procedure, there is a property of the attribute, called IsComposable. If IsComposable is true, then the method will consider calling function in database, otherwise it will consider to call stored procedure.

 

For return type of them, returning ISingleResult<Classname> is intended for stored procedure, System.Nullable<type> return type is intended for scalar function and IQueryable<Classname> return type is intended for table value function.

 Stored procedure

Sample method :

 

[Function(Name="[dbo].[Customers By City]")]

public ISingleResult<Customer> CustomerByCity(string param1)

{

    return (ISingleResult<Customer>)(this.ExecuteMethodCall(this, (MethodInfo)MethodInfo.GetCurrentMethod(), param1).ReturnValue);

}

  Scalar function

Sample method :

 

[Function(Name="dbo.MinUnitPriceByCategory",IsComposable=true)]

public System.Nullable<decimal> MinUnitPriceByCategory(int categoryID)

{

    System.Nullable<decimal> result = (System.Nullable<decimal>)this.ExecuteMethodCall(this, (MethodInfo)MethodInfo.GetCurrentMethod(), categoryID).ReturnValue;

    return result;

}

 Table value function

Sample method :

 

[Function(Name = "[dbo].[GetCustomerInfo]",IsComposable=true)]

public IQueryable<Customer> GetCustomerInfo(string param1)

{

    return (IQueryable<Customer>)(this.ExecuteMethodCall(this, (MethodInfo)MethodInfo.GetCurrentMethod(), param1).ReturnValue);

}

 

You can also see generated code from Visual Studio by add new item, then select LINQ to SQL classes, then in the new designer window you drag stored procedure or function into. You can see generated code in file <filename>.designer.cs, or you can also generate csharp file from SQLMetal command line utility.

 

In main program, you can call all these methods by code below :

class Class1{    public static void Main()    {        SampleDb sampleDB = new SampleDb(new SqlConnection(your connection string));         foreach (var row in sampleDB.CustomerByCity("Seattle"))        {            Console.WriteLine(row.CustomerID + " - " + row.CompanyName);        }         Console.WriteLine();         var query = sampleDB.MinUnitPriceByCategory(1);         Console.WriteLine(query);         Console.WriteLine();         foreach(var row in sampleDB.GetCustomerInfo("ALFKI"))        {            Console.WriteLine(row.CompanyName + " - " + row.City);        }         Console.ReadLine();    }} 

SampleDB class is derived from DataContext base class.

Share this post: | | | |
Posted: Nov 29 2007, 08:15 AM by Kasim.Wirama | with 1 comment(s)
Filed under:
Lambda Expression as Predicate and Expression Tree in C# 3.0

Lambda Expression as Predicate and Expression Tree in C# 3.0

By : Kasim Wirama, MCSD.NET, MVP SQL Server

 

One of C# 3.0 new feature is lambda expression. What is it actually Lambda expression? How to use Lambda expression?

 

In C# 2.0, ability to pass method implementation to a delegate type is called anonymous method. In C# 3.0 with lambda expression, you can make definition of anonymous method is more concise.

 

Syntax of lambda expression has sign/operator => (combination of equal and greater than sign)

 

Typical use of simple delegate is provided in example below:

public delegate void MethodDlgt(string a, string b);

class Class1

                public static void Main()
                {
                                MethodDlgt dlgt = Method1;
                                dlgt("hello", "world");
                                Console.ReadLine();
                }

                public static void Method1(string a, string b)
                {
                                Console.WriteLine("{0} {1}", a, b); 
                }
}

It will output "Hello World" message to console application when the sample above is run.

With lambda expression this sample above could be written as follows :

public delegate void MethodDlgt(string a, string b);

class Class1
{
                public static void Main()
                {
                                MethodDlgt dlgt = (a, b) => { Console.WriteLine("{0} {1}", a, b); };
                                dlgt("hello", "world"); 
                                Console.ReadLine();
                }
}

As you can compare, the static method Method1 is directly assigned to delegate variable dlgt.

Delegate type before class declaration could be replace with built-in delegate type called Func, with has last parameter as return value with generic type, so the above example could be in more concise form as below :

class Class1
{
                public static void Main()
                {
                                Func<string, string,bool> dlgt = (a, b) => { Console.WriteLine("{0} {1}", a, b); return true; };
                                dlgt("hello", "world"); 
                                Console.ReadLine();
                }
}

Another example, that make clear use of lambda expression, is to pass method execution through input parameter.

class Class1

                public static void Main1()
                {
                                string[] names = { "ali", "marco", "stephan" };
                                Display<string>(names, 4); Console.WriteLine();
                                Display<string>(names, "ali");
                                Console.ReadLine();
                }

                public static void Display<T>(T[] param1, string value)
                {
                                foreach(T member in param1)
                                {
                                if (string.Equals(member , value))
                                                {
                                                                Console.WriteLine(member);
                                                }
                                }
                }

                public static void Display<T>(T[] param1, int length)
                {
                                foreach (T member in param1)
                                {
                                                if (member.ToString().Length >= length) 
                                                {
                                                                Console.WriteLine(member);
                                                }
                                }
                }
}

There are 2 overloading method, first method is to display searched value, second one is to display collection members that satisfy string length criteria. With lambda expression I could move if (member.ToString().Length >= length) { Console.WriteLine(member); } and if (string.Equals(member , value)) { Console.WriteLine(member); } into Main method, and reduce overloading method Display from 2 become 1, here is the code :

class Class1
{
                public static void Main()
                {
                                string[] names = { "ali", "marco", "stephan" };
                                Display(names, "ali", (member, b) => {if (member == b) { Console.WriteLine(member); }
                                                                                return true;
                                                                                       }
                                                );
                                Console.WriteLine();
                                Display(names, 3, (member, b) => { if (member.Length > b) {Console.WriteLine(member); } 
                                                                                                                return true; }
                                                );
                                Console.ReadLine();
                }

                public static void Display<T,U,B>(T[] param1, U param2, Func<T,U,B> s)
                {
                                foreach (T member in param1)
                                {
                                                s(member, param2);
                                }
                }
}

It is a bit confusing at first time, the way you understand the order of execution is to debug through visual studio and you will get the point.

Usually delegate is assigned to lambda expression. On this example, lambda expression is used as predicate. What is predicate?

Predicate is a Boolean expression, for example :

(a) => a > 5

Other terms is projection. Projection is a lambda expression that returns different type from input type

For example :

(a) => a.Length

a as string in input parameter, and return integer value from a.Length.

You should remember that lambda expression is not tied to built-in delegate (Func), it can be used with your own specified delegate.

Besides that, lambda expression can be used with Expression class. Expression class resides under System.Linq.Expressions. Here is the example :

class Class1
{
                private delegate T Func<T>(T a, T b);

                public static void Main1()
                {
                                Expression<Func<int>> y = (a , b) => a + b; 
                                Console.WriteLine(y.Compile()(5, 7));
                                Console.ReadLine();
                }
}

There is method Compile on expression instance. Compile here returns a delegate that invoked by Invoke method. Expression tree is used in generating SQL statement by LINQ’s method by navigating the expression tree.

From these examples above, I can conclude that predicate with lambda expression is make your code shorter, and make your function is more flexible with greater coverage range of functionality through lambda expression.

It is our learning curve to grab lambda expression into daily .NET 3.5 codes.

Share this post: | | | |
Posted: Nov 29 2007, 07:10 AM by Kasim.Wirama | with 38 comment(s)
Filed under:
Querying into Database with LINQ

Querying into Database with LINQ

By : Kasim Wirama, MCDBA, MVP SQL Server

 

This article, you can begin your exploration of LINQ into database. The LINQ to SQL concept is intended to provide thin layer between application and database. Purpose of LINQ is to give interoperability to any database platform through its object DataContext.

 

When I see overloading constructor of DataContext, one of the overloading constructor receiving interface of database connection (IDbConnection), it means that as long as particular database platform inherits from the interface, it can be reached by LINQ. DataContext itself reside on namespace System.Data.Linq;

 

Every table will have their class. So it needs mapping between their class name and the table name through attribute Table that decorates the class name. where does the mapping reside? It resides under System.Data.Linq.Mapping namespace. Because each class has mapping attribute, it is called entity class. Each columns of the table will have to corresponding entity class members through mapping attribute Column. It is better to have attribute property IsPrimaryKey=true in one or more columns member of each entity class.

 

Here is the example :

    [Table(Name="Customers")]

    public class Customer

    {

        [Column(IsPrimaryKey=true)]

        public string CustomerID;

       

        [Column]

        public string CompanyName;

       

        [Column]

        public string City;

       

        [Column(Name="Region")]

        public string State;

       

        [Column]

        public string Country;

    }

 

Class Customer is mapped to Customers table.

 

Other class is :

    [Table(Name="Orders")]

    public class Order

    {

        [Column(IsPrimaryKey = true)]

        public int OrderID;

 

        [Column()]

        public string CustomerID;

 

        [Association(Storage="_Customer",ThisKey="CustomerID")]

        public Customer Customer

        {

            get { return this._Customer.Entity; }

            set { this._Customer.Entity = value; }

        }

 

        private EntityRef<Customer> _Customer;

    }

 

You see Association attribute and EntityRef type. Association attribute will link Customer object to the key CustomerID, and EntityRef defines the entity class Order has foreign key relationship to Customer entity class.

 

In main class you can connect to database through LINQ datacontext object with :

DataContext db = new DataContext(new SqlConnection(your connection string));

 

This instance will bridge between your application and relational world, and transforming from object relational query into SQL.

 

You can see SQL output from datacontext by putting this code :

db.Log = Console.Out;

 

After that you get instance of entity class by issuing :

Table<Order> orders = db.GetTable<Order>();

 

If you want to get orders comes from USA you can issue :

Var result = from o in orders

                        Where o.Customer.Country == “USA”

                        Select o.OrderID;

 

You can output the result with code below :

Foreach (var item  in result)

{

  Console.WriteLine (item);

}

 

You can see join syntax query in console window. That’s the SQL command translated from object querying.

Share this post: | | | |
Posted: Nov 29 2007, 12:52 AM by Kasim.Wirama | with no comments
Filed under:
First time with LINQ
st1\:*{behavior:url(#ieooui) }

First time with LINQ

By : Kasim Wirama, MCDBA, MVP SQL Server

 

I am wondering what LINQ looks like. So I begin my exploration to LINQ from simple query to most complex one. I would like to describe a little what LINQ is. LINQ is a gateway between object oriented paradigm in .NET and relational paradigm in database. What was being a problem before LINQ revolutionaries the way how programmer develop database application with .NET? The old time programmer develops 2 kinds of language, .NET language and SQL. And there is no compile time checking for SQL code in .NET until run time error originated from database raises.

 

With LINQ, programmer has better way to make sure the SQL code run well, and programmer doesn’t have to code in SQL, they can write object relational code that in turns translated by .NET into SQL language under the hood. Actually LINQ is not just around database, it also covers querying to instance of object, and XML world. I can say it is most important new feature of .NET 3.5.

 

This article, I would introduce you basic querying with LIN        Q, as subsequent articles, we will see more further about LINQ capabilities.

 

Lets start with 3 simple class below :

 

Public class Customer

{

Public string customerName;

Public Order[] orders;

Public string city;

Public string country

}

 

Public class Order

{

Public int orderID;

Public int productID;

Public int qty;

}

 

Public class Product

{

Public int productID;

Public decimal price;

}

 

Public class Program

{

public static void Main()

{

            PopulateAndRunQueries();

            Console.ReadLine(