Search

Aug 19, 2008

Best way to generate XML using LINQ

Hi all,

As we know C# 3.0 with LINQ gives us lots of power and smart coding, here is one more example which uses features of LINQ to generating XML of the abstract type.

I will give you example where you need to display the person details along with the address, here address can be anything like home address, email address, IM address ...

Here are the classes which require to achive our goal.

class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public List<Address> Address = new List<Address>();
}

class Address
{
public string AddressValue { get; set; }
public string Type { get; set; }
}

Person class used to store person data, and Address class which holds the type of address.
Now lets add few details.

Person Person1 = new Person() { FirstName = "Imran", LastName = "Bhadelia" };
Person1.Address.Add(new Address() { Value = "imran.bhadelia[at]gmail.com", Type = "Email" });
Person1.Address.Add(new Address() { Value = "bhadelia.imran[at]gmail.com", Type = "AlternativeEmail" });
Person1.Address.Add(new Address() { Value = "bhadelia.imran[at]gmail.com", Type = "MSNInstanceMessanger" });
Person1.Address.Add(new Address() { Value = "bhadelia.imran", Type = "YahooInstanceMessanger" });

Person Person2 = new Person() { FirstName = "Armaan", LastName = "Bhadelia" };
Person2.Address.Add(new Address() { Value = "armaan.bhadelia[at]gmail.com", Type = "Email" });
Person2.Address.Add(new Address() { Value = "Sweet Home, 406 Paradise Palace...", Type = "Residence" });
Person2.Address.Add(new Address() { Value = "bhadelia.armaan[at]gmail.com", Type = "MSNInstanceMessanger" });
Person2.Address.Add(new Address() { Value = "bhadelia.armaan", Type = "YahooInstanceMessanger" });

List<Person> PersonList = new List<Person>();
PersonList.Add(Person1);
PersonList.Add(Person2);

Here I used one feature of C#3.0, which is Object Initialization Expressions. See the constructor of both class, Its default and while creating object I am setting the value to the fields of class [Smart coding]. I added this two class into List variable, from where LINQ will generate XML which looks like...

<Persons>
<Person FirstName="Imran" LastName="Bhadelia">
<Address Email="imran.bhadelia[at]gmail.com" />
<Address AlternativeEmail="bhadelia.imran[at]gmail.com" />
<Address MSNInstanceMessanger="bhadelia.imran[at]gmail.com" />
<Address YahooInstanceMessanger="bhadelia.imran" />
</Person>
<Person FirstName="Armaan" LastName="Bhadelia">
<Address Email="armaan.bhadelia[at]gmail.com" />
<Address Residence="Sweet Home, 406 Paradise Palace..." />
<Address MSNInstanceMessanger="bhadelia.armaan[at]gmail.com" />
<Address YahooInstanceMessanger="bhadelia.armaan" />
</Person>
</Persons>

And now LINQ to generate above XML.

var PersonXml =
new XElement("Persons",
from person in PersonList
select (new XElement("Person",
new XAttribute("FirstName", person.FirstName),
new XAttribute("LastName", person.LastName),

from addr in person.Address
select new XElement("Address", new XAttribute(addr.Type, addr.Value)))));

Console.WriteLine(PersonXml.ToString());

How it works??
Line#2: Create the main element which is Persons
Line#3: Getting single Persons object from PersonList
Line#4: Creating sub element to Persons which is Person
Line#5&6: Creating attributes to show person details.
Line#8: Getting Address of the person from Address collection
Line#9: Creating Address element along with the attribute

Easy? I found its very easy :)

Now if you want to add this information into SQL Server 2005 and higher, you can pass it as string and in your procedure grab the value. There are lots of way to grab value from XML in SQL, you can check this url, it has almost all the operations to XML datatype in SQL.

I created SQL script for specific to this xml.

SELECT 
Person.value('@FirstName[1]', 'VARCHAR(100)') as FirstName,
Person.value('@LastName[1]', 'VARCHAR(100)') as LastName,
Person.value('(Address/@Email)[1]', 'VARCHAR(100)') as Email,
Person.value('(Address/@AlternativeEmail)[1]', 'VARCHAR(100)') as AlternativeEmail,
Person.value('(Address/@Residence)[1]', 'VARCHAR(100)') as Residence,
Person.value('(Address/@MSNInstanceMessanger)[1]', 'VARCHAR(100)') as MSNInstanceMessanger,
Person.value('(Address/@YahooInstanceMessanger)[1]', 'VARCHAR(100)') as YahooInstanceMessanger
FROM @Persons.nodes('/Persons/Person') p(Person)

Aug 13, 2008

Getting child ids in string separate with delimiter along with parent id[SQL SERVER]

Hi Friends,

I come accros one requirement where I need... the child id should be delemited by '|' and along with the parent Id. Lets say I am having parent as company, one company is having more then one code.

So now my requirement is to get the company code in '|' saperated with company id, just like this.

Comp_id     company_code
----------- ------------
1 1|2
2 1|2|3|4
3 1|2

We can achive this by either using a user-defined aggregate function or using loop. I will explore the user-defined aggreagate function and post how to do, but for now lets do it with looping. Here is the code to achive this by using while-loop.

DECLARE @companies Table
(
Comp_id INT,
company_code int
)

insert into @companies values(1,1)
insert into @companies values(1,2)
insert into @companies values(2,1)
insert into @companies values(2,2)
insert into @companies values(2,3)
insert into @companies values(2,4)
insert into @companies values(3,1)
insert into @companies values(3,2)

DECLARE @TmpTable Table
(
Id int IDENTITY (0, 1) NOT NULL,
CompanyId INT
)

SET NOCOUNT ON

DECLARE @Tmpcompanies Table
(
Comp_id int,
company_code varchar(10)
)

INSERT INTO @TmpTable SELECT DISTINCT comp_id FROM @companies

DECLARE @MaxId INT
DECLARE @PipedList VARCHAR (MAX)
Declare @Count INT
Declare @CurrComp INT

SELECT @MaxId = MAX(id) FROM @TmpTable
SET @Count = 0
WHILE( @Count <= @MaxId)
BEGIN
SET @PipedList = NULL
SELECT @CurrComp = Comp_id, @PipedList = COALESCE(CAST(@PipedList AS VARCHAR(MAX)) + '|', '')
+ CAST(company_code AS VARCHAR(10)) FROM @companies Cmp, @TmpTable TT
WHERE CMP.Comp_id = TT.CompanyId AND TT.ID = @Count
INSERT INTO @Tmpcompanies VALUES(@CurrComp, @PipedList)
SET @Count = @Count + 1
END

SELECT * FROM @Tmpcompanies

Aug 12, 2008

How to sort generic collection

Hi all,

We will now sort generic collection. For this we need to create one comparere class which inherits IComparer<T> and implement Compare method, where T is your class object. Compare method is responsible to compare tow object and based on the result sorting will be done.

public class TestSortComparere : IComparer<TestSort>
{
public TestSortComparere() { }

#region IComparer<TestSort> Members

public int Compare(TestSort x, TestSort y)
{
return string.Compare(x.a, y.a);
}

#endregion
}

Now lets call Sort method.

List<TestSort> MyObjList = new List<TestSort>();
MyObjList.Add(new TestSort("Imran"));
MyObjList.Add(new TestSort("Dipak"));
MyObjList.Add(new TestSort("Sachin"));
MyObjList.Add(new TestSort("Darshan"));
MyObjList.Add(new TestSort("Gaurav"));

MyObjList.Sort(new TestSortComparere());

You can see the sorted order when you iterate MyObjList

foreach (TestSort testSort in MyObjList)
Console.Write(testSort.strTest + Environment.NewLine);
//OUTPUT
/*
Darshan
Dipak
Gaurav
Imran
Sachin
*/

We can change the sort line using Anonymous delegate. Lets see how, its only in single line!!!!.

MyObjList.Sort(delegate(TestSort x, TestSort y) { return string.Compare(x.strTest, y.strTest); });

Difference between internal and protected internal

Hi All,

Generally what we assume that internal means the variable that can only accessed within the assembly [which is the collection of namespace and classes].

But there is slide different meaning when we add protected to an internal member. What is that? The difference is... if you created a member which is protected internal then you can get it outside the assembly, but condition that you derive that class. Its protected so if you derive that class then in child class you can access the protected internal member.

We can check it out with example. Lets have a look at the classes which are in same assembly.

namespace Understand
{
public class C : UnderstandInternal.Class1
{
public C()
{
base.intInternalProtected(); // can call anything
base.intInternal();
}
}
}


namespace UnderstandInternal
{
public class Class1
{
internal int intInternal() { return 1; }
internal protected int intInternalProtected() { return 3; }
}


public class Class3
{
Class1 c = new Class1();
public Class3()
{
c.intInternalProtected(); // can call anything
c.intInternal();
}
}
}




You can see there is no problem in accessing the variable, its working fine, now we will do same thing in different assembly. Lets look at the following classes.








namespace TestConsole
{
class InternalTest : Class1
{
public InternalTest()
{
base.intInternalProtected(); //your can use here
base.intInternal(); //Error: 'UnderstandInternal.Class1' does not contain a definition for 'intInternal'

}
}

class Program
{
static void Main(string[] args)
{
Class1 c = new Class1();
c.intInternalProtected(); //Error: 'UnderstandInternal.Class1.intInternalProtected()' is inaccessible due to its protection level
c.intInternal(); //Error: 'UnderstandInternal.Class1' does not contain a definition for 'intInternal' and no extension method 'intInternal'
}
}
}

Transferring control from ascx to aspx

Hi all,

In many cases we require some functionality in which there is something happening at control level and we need to notify to page level. Mainly when we are creating control which has grid or some short of dataview control and there is need to pass some message to page [in which the control is loaded] from any event.

This article will help you to achive this using a powerful functionality provided by .NET framwork which is delegate. Delegate in C# is similar to a function pointer in C or C++. Using a delegate allows the programmer to encapsulate a reference to a method inside a delegate object. The delegate object can then be passed to code which can call the referenced method, without having to know at compile time which method will be invoked.

Our goal is to display the messages on page [aspx] about which row is currently selected. We will create one event in control [ascx] which will be handeled in page [aspx], for creating event we need to create one delegate first.

public delegate void SelectedIndexChanging(object sender, GridViewSelectEventArgs e);

SelectedIndexChanging is the delegate which has same argument as GridView's SelectedIndexChanging event.

Now will create Event of the type SelectedIndexChanging delegate in ascx

public event SelectedIndexChanging GridViewSelectedIndexChanging;

How to call this event? Well we have to call this event on the same event of Grid in ascx, so we can raise this event and in page [aspx] we can capture this and do the some operation.

protected void gvTest_SelectedIndexChanging(object sender, GridViewSelectEventArgs e)
{
if (GridViewSelectedIndexChanging != null)
GridViewSelectedIndexChanging(sender, e);
}

Why null condition check? We have to check whethere there is any handler to this event or not, if there is no handler bound then no need to raise this event, else it will thro Exception :)
We are ready with our user control, now place this on page and bind the hendler to SelectedIndexChanging event, here is the bind code.

childControl.GridViewSelectedIndexChanging += new ChildControl.SelectedIndexChanging(childControl_GridViewSelectedIndexChanging);

And in method I am just displaying the selected item details.

void childControl_GridViewSelectedIndexChanging(object sender, GridViewSelectEventArgs e)
{
GridViewRow gvr = (sender as GridView).Rows[e.NewSelectedIndex];
lblGridSelectedFor.Text = string.Format("Id = {0}, Name = {0}",
(gvr.FindControl("lblIdentity") as Label).Text, (gvr.FindControl("lblName") as Label).Text);
}

As I passed the same sender along with GridViewSelectEventArgs, I can access all the events and gridview here. First I cast sender in GridView to get the GridView which is inside user control, and from NewSelectedIndex, I read some value and displaying using label.

And this way we achive our goal, you can do lots many thing by use of Delegates, you can also read the article on Anonymous Delegate and Delegates and Events in C# / .NET

Aug 9, 2008

Parent can hold reference of Child

Hello all,

We all know that A a = new B(); we learn this by heart from the day we start OOPS.

But there are lots many people who just do cramming lolz, I have one good example which helps you to get your mind set what is meaning of A a = new B();

We all know that using virtual function we can achive the golden word "Parent can hold reference of child", but its not just virtual function involved, there are also reusability.

Lets say you have one base class having 10 properties and you derived 2 more classes which individual has more then 5-5 properties.

So what I do? Should I create methods for each child class? What if I have more 2-3 class?? The answer is NO [I knew that you know it :)]

So what to do? How A a = new B(); will help full here?

Lets learn with example.

I am haivng A as parent class and B, C as child class.
class A
{
public int Id { get; set; }

public virtual void PrintMe()
{
Console.WriteLine("Id : " + Id);
}

}

class B : A
{
public string Name { get; set; }

public override void PrintMe()
{
base.PrintMe();
Console.WriteLine("Name : " + Name);
}
}

class C : A
{
public string Company { get; set; }
public override void PrintMe()
{
base.PrintMe();
Console.WriteLine("Company : " + Company);
}
}
You can see the virtual method; this is the key thing to see the power of A a = new B();.

Now the method call, here is the code to calling method PrintMe

A a = new B();
a.PrintMe(); //will call B method
a = new A();
a.PrintMe(); //Will call A method
a = new C();
a.PrintMe(); //Will call C method
There is nothing wrong in it, it can easily understood.

Now our purpose, what is it? Yes we need to set properties and then call PrintMe method.

private static void CallMe(A a)
{
a.Id = 4;

if (a is C)
((C)a).Company = "My Company";
else if (a is B)
((B)a).Name = "My Name";
a.PrintMe();
}
See the signature of this method, it says private static void CallMe(A a), the parameter is object of class A; that is PARENT. And inside it the first line is setting the property of parent and then based on the type the rest of properties is getting populated. And at the end calling PrintMe which is virtual so based on reference it will call the method.

Lets call method CallMe.

1. a = new B();
2. CallMe(a); //Will print Id and Name
3. a = new C();
4. CallMe(a); //Will print Id and Company
1st line creating object of B and setting it to A'a object. 2nd linke calling CallMe by passing the parent object. This will first set the property of child and then as its B's object will set the property of Name and call PrintMe, which give call to B's PrintMe method [remember virtual].

So, this is the real world use of A a = new B();

Hope you understand, any question any query please feel free to approch me.

Aug 8, 2008

Inserting collection of string to DB with duplicate check

Hi all,

We need some kind of functionality where from frontend [ASP.NET] we pass the comma or semicolon saperated strings into database for inserting purpose and also we need to check the duplication of the string.

With the world of XML we can do this easily, here is the Sql Script to do so. My string collection is the email list, i have to insert multiple emails and also need to check for the duplication. at the end I get the duplicate email list, which can be easily get form Frondend [ADO.NET] using output param or any other way.

SET NOCOUNT ON

DECLARE @Table AS TABLE
(
Email VARCHAR(100)
)

INSERT INTO @Table VALUES('a@b.com')
INSERT INTO @Table VALUES('c@d.com')

DECLARE @EmailList VARCHAR(MAX)
DECLARE @XMLEmailList XML

SELECT @EmailList = 'a@b.com;c@d.com;aa@aa.com;fads@ddd.com'
SELECT @XMLEmailList= '<email>' + REPLACE(@EmailList, ';', '</email><email>') + '</email>'

DECLARE @DuplicateEmail VARCHAR(100)

SELECT @DuplicateEmail = COALESCE(CAST(@DuplicateEmail AS VARCHAR(MAX)) + ';', '') + + CAST(a.value('.', 'varchar(100)') AS VARCHAR(10))
FROM @XMLEmailList.nodes('/email') v(a)
WHERE a.value('.', 'varchar(100)') in (SELECT Email FROM @Table)

INSERT INTO @table
SELECT a.value('.', 'varchar(100)')
FROM @XMLEmailList.nodes('/email') v(a)
WHERE a.value('.', 'varchar(100)') not in (SELECT Email FROM @Table)

SELECT @DuplicateEmail
SELECT * FROM @Table

Inserting value of Collection into Database

We always require thing like this, when you need to Insert list of object at the same time with single database operation.

Generally what we are doing is inserting individual object from front end, which is not good idea; in case where you have 100 of object needs to be inserted same time.

With the new feature Extension Method included in C# 3.0 and the XML datatype provided in SQL Server 2005, with combining these two we can achive the goal with less affort in terms of traffic and compactness of code.

I posted code on Code Project, it has description of each important phase you can download and customize according your need.

Aug 7, 2008

Remove duplicate comma from list

Hi,

Recently on ASP.NET forum there was post for removing duplicate ',' from a comma saperated string.

This is using Regex
string abodes = ",House,,,,Apartment,,,Villa,,,,Townhouse,,,,";
Regex regx = new Regex(@",+");
abodes = regx.Replace(abodes, ",").Trim(',');
And now let's see using LINQ
string abodes = ",House,,,,Apartment,,,Villa,,,,Townhouse,,,,"; 
string cleanAbodes = string.Join(",", abodes.Split(',').Where(a => a != string.Empty).ToArray());
Have Fun with LINQ

Aug 4, 2008

Expression in ASP.NET

What if I want to show the value of the key defined in Web.config file on a ASPX page? Or for testing purpose if we want to show the value of connection string??

Here is the Web.Config file entries...
<appSettings>
<add key="ImageFolder" value="C:\Temp"/>
</appSettings>
<connectionStrings>
<add name="DBConnection" providerName="System.Data.SqlClient"
connectionString="Data Source=[DataSource];Initial Catalog=[InitialCatalog];
User ID=[UserID];Password=[Password]"
/>
</connectionStrings>
And here is the general code:
Response.Write(ConfigurationManager.AppSettings["ImageFolder"]);
Response.Write(ConfigurationManager.ConnectionStrings["DBConnection"].ConnectionString);
Now lets use the expression....
<asp:Label ID="lblDBConnection" runat="server" Text='<%$ connectionStrings:DBConnection %>' />
<asp:Label ID="lblImageFolder" runat="server" Text='<%$ appSettings:ImageFolder %>' />

So simple!!!
The <%$ and %> tags are used to mark an expression that should be parsed by an ExpressionBuilder. Because of the prefix ConnectionStrings and appSettigs are already mapped to the particular ExpressionBuilder class that is responsible for parsing the expression; we dont need to do any extra afford.

Here are the default ExpressionBuilder classes provided by ASP.NET framework.


  1.  AppSettingsExpressionBuilderRetrieves values from the appSettings section of the web configuration file.

  2.  ConnectionStringsExpressionBuilderRetrieves values from the connectionStrings section of the web configuration file.

  3.  ResourceExpressionBuilderRetrieves values from resource files.



The ExpressionBuilder must always be used with control properties as I used in my example. You can create a custom ExpressionBuilder when none of the existing ExpressionBuilder classes do what you need, for this you must implement the ExpressionBuilder abstract class. Read More