Download the unity dll's from http://unity.codeplex.com/
I. Without Registering Type/Instance
By the documents of Unity, we have:
"You can use the Unity container to generate instances of any object that has a public constructor (in other words, objects that you can create using the new operator), without registering a mapping for that type with the container. When you call the Resolve method and specify the default instance of a type that is not registered, the container simply calls the constructor for that type and returns the
result."
We write the following code to test:
class Program
{
static void Main(string[] args)
{
IUnityContainer container = new UnityContainer();
MyService serviceInstance = container.Resolve< MyService>();
serviceInstance.Print("End of 2010.");
}
public class MyService
{
public void Print(string msg)
{
Console.WriteLine("Hello," + msg);
}
}
}
The Unity Application Block exposes two methods for registering types and mappings with the container:
II. Register Type
This method register a type with the container and at the appropriate time the container will build an instance of the type you specified.
Let's first Create an interface called IWriteService,
public interface IWriteService
{
void Write(string msg);
}
And we create 4 concrete classes
public class FirstService : IWriteService
{
public void Write(string msg)
{
Console.WriteLine("First Service: "+msg);
}
}
public class SecondService : IWriteService
{
public void Write(string msg)
{
Console.WriteLine("Second Service: " + msg);
}
}
public class ThirdService : IWriteService
{
public void Write(string msg)
{
Console.WriteLine("Third Service: " + msg);
}
}
public class FourthService : IWriteService
{
public void Write(string msg)
{
Console.WriteLine("Fourth Service: " + msg);
}
}
In the Main entry, we can register the Service with mapping.
IUnityContainer container = new UnityContainer();
//Do not specify the name, will be the default mapping
container.RegisterType< IWriteService, FirstService>();
//notice we use the RegisterType< TFrom, TTo >, this creats a mapping
//we can also use RegisterType< T>
//Specify the name
container.RegisterType< IWriteService, SecondService>("Second");
//We can also use register chain
container.RegisterType< IWriteService, ThirdService>("Third")
.RegisterType< IWriteService, FourthService>("Fourth");
So when resolve, we can specify the name or use the default mapping.
IWriteService serviceInstance1 = container.Resolve< IWriteService>();
serviceInstance1.Write("test");
IWriteService serviceInstance2 = container.Resolve< IWriteService>("Second");
serviceInstance2.Write("test");
IWriteService serviceInstance3 = container.Resolve< IWriteService>("Third");
serviceInstance3.Write("test");
We can also use ResolveAll method to get the IEnumerable< IWriteService> Collection:
IEnumerable< IWriteService> serviceInstances = container.ResolveAll< IWriteService>();
foreach (IWriteService service in serviceInstances)
{
service.Write("good");
}
The source code is at:
https://docs.google.com/uc?id=0BwzR-spEXHBFZjU1ZjUxMWMtNTg1ZS00MWRiLTg2M2MtY2MzZDBiNDUwMTAw&export=download&hl=en
III. Register Instance
We can also register instance to the container.
We write class the following:
public class FifthService : IWriteService
{
public void Write(string msg)
{
Console.WriteLine("Fifth Service: " + msg);
}
}
And in the Main entry, we write code to register and resolve instance like the following:
container.RegisterInstance< IWriteService>(new FifthService());
IWriteService service5 = container.Resolve< IWriteService>();
service5.Write("Register Instance");
Thursday, December 30, 2010
Friday, December 17, 2010
Cast IEnumverable< T> to ObservableCollection< T>
My sample code:
using System.Collections.Generic;
using System.Collections.ObjectModel;
class Program
{
static void Main(string[] args)
{
ObservableCollection< Employee> obc = new ObservableCollection< Employee>(GetEployeeList());
}
public static IEnumerable< Employee> GetEployeeList()
{
for (int i = 0; i < 5; i++)
{
yield return new Employee { ENumber = i + 1, EName = "Name" + (i + 1).ToString() };
}
}
}
public class Employee
{
public int ENumber { get; set; }
public string EName { get; set; }
}
using System.Collections.Generic;
using System.Collections.ObjectModel;
class Program
{
static void Main(string[] args)
{
ObservableCollection< Employee> obc = new ObservableCollection< Employee>(GetEployeeList());
}
public static IEnumerable< Employee> GetEployeeList()
{
for (int i = 0; i < 5; i++)
{
yield return new Employee { ENumber = i + 1, EName = "Name" + (i + 1).ToString() };
}
}
}
public class Employee
{
public int ENumber { get; set; }
public string EName { get; set; }
}
Wednesday, December 15, 2010
About DataContext Class
In Linq to Sql, if we added a Linq to Sql Class, there will created a MyClassDataContext which is inherited from DataContext Class. It is included in System.Data.Linq namespace.
"The DataContext provides connection-like functionality for us and has many capabilities such as executing commands, providing access to collections of entities from the database and identity and tracking services. "
I. Use DataContext to Create a DataBase
We should first create a Table Class included in our DataContext instance, otherwise DB is not allowed to be created.
The Table Attribute comes from using System.Data.Linq.Mapping namespace.
We can use LinqtoSql drag in the desinger to see how a table class looks like, we can check msdn:
http://msdn.microsoft.com/en-us/library/Bb399420(v=VS.90).aspx
Notice, we can use mdf file to create db as well.
Let's take an example:
[Table(Name = "Project")]
public class Project
{
[Column(IsPrimaryKey = true)]
public int PID;
[Column]
public string PName;
[Column]
public string PPerson;
}
And we create a MyDataContext Class overriding the class Context.
public class MyDataContext : DataContext
{
public Table Projects;
public MyDataContext(string constr)
: base(constr)
{
}
}
In this case we can use DataContext to create a database:
MyDataContext mctx = new MyDataContext("server=myServer;Database=MyDB;User Id=Jie Zhu;password=12345");
mctx.CreateDatabase();
2. Use DataContext to Delete a DataBase.
DataContext ctx2 = new DataContext("server=myServer;Database=MyDB;User Id=Jie Zhu;password=12345");
ctx2.DeleteDatabase();
3.Use DataContext to Execute a Sql Command.
DataContext ctx = new DataContext("server=myServer;Database=MyDB;User Id=Jie Zhu;password=12345");
ctx.ExecuteCommand("Insert Project(PID,PName,PPerson) values(1,'Project1','Jack')");
ctx.ExecuteCommand("Insert Project values({0},{1},{2})", 2, "Project2","Amy");
4.Use Context GetTable Method
DataContext ctx = new DataContext("server=myServer;Database=MyDB;User Id=Jie Zhu;password=12345");
foreach (Project p in ctx.GetTable())
{
Console.WriteLine(p.PName);
}
5.Use Context to Translate DataReader
We can use DataContext to translate the DataReader to our objective type.
We create a static method:
static SqlDataReader GetProject(SqlConnection con)
{
con.Open();
SqlDataReader reader;
using (SqlCommand cmd = new SqlCommand("Select * from Project", con))
{
reader = cmd.ExecuteReader();
}
return reader;
}
In this case we can use:
MyDataContext mctx = new MyDataContext("server=myServer;Database=MyDB;User Id=Jie Zhu;password=12345");
foreach (Project p in mctx.Translate(GetProject(new SqlConnection("server=myServer;Database=MyDB;User Id=Jie Zhu;password=12345"))))
{
Console.WriteLine(p.PPerson);
}
6.Use DataContext ExcuteQuery method
IEnumerable ProjectCollection = ctx.ExecuteQuery("Select * from Project");
foreach (Project p in ProjectCollection)
{
Console.WriteLine(p.PID);
}
7. Use DataContext SubmitChanges to Update Table
MyDataContext mctx = new MyDataContext("server=myServer;Database=MyDB;User Id=Jie Zhu;password=12345");
Project p1 = mctx.Projects.Single(p => p.PID == 2);
p1.PPerson = "Erica";
mctx.SubmitChanges();
After we know DataContext clearly here, we know the internal mechanism of Linq to Sql.
For example, we create a Linq to Sql class called MyDataClasses, after database configuration and Table dragging to the designer. It created corresponding DataContext and DataTable classes. You can look at MyDataClasses.designer.cs file.
"The DataContext provides connection-like functionality for us and has many capabilities such as executing commands, providing access to collections of entities from the database and identity and tracking services. "
I. Use DataContext to Create a DataBase
We should first create a Table Class included in our DataContext instance, otherwise DB is not allowed to be created.
The Table Attribute comes from using System.Data.Linq.Mapping namespace.
We can use LinqtoSql drag in the desinger to see how a table class looks like, we can check msdn:
http://msdn.microsoft.com/en-us/library/Bb399420(v=VS.90).aspx
Notice, we can use mdf file to create db as well.
Let's take an example:
[Table(Name = "Project")]
public class Project
{
[Column(IsPrimaryKey = true)]
public int PID;
[Column]
public string PName;
[Column]
public string PPerson;
}
And we create a MyDataContext Class overriding the class Context.
public class MyDataContext : DataContext
{
public Table
public MyDataContext(string constr)
: base(constr)
{
}
}
In this case we can use DataContext to create a database:
MyDataContext mctx = new MyDataContext("server=myServer;Database=MyDB;User Id=Jie Zhu;password=12345");
mctx.CreateDatabase();
2. Use DataContext to Delete a DataBase.
DataContext ctx2 = new DataContext("server=myServer;Database=MyDB;User Id=Jie Zhu;password=12345");
ctx2.DeleteDatabase();
3.Use DataContext to Execute a Sql Command.
DataContext ctx = new DataContext("server=myServer;Database=MyDB;User Id=Jie Zhu;password=12345");
ctx.ExecuteCommand("Insert Project(PID,PName,PPerson) values(1,'Project1','Jack')");
ctx.ExecuteCommand("Insert Project values({0},{1},{2})", 2, "Project2","Amy");
4.Use Context GetTable Method
DataContext ctx = new DataContext("server=myServer;Database=MyDB;User Id=Jie Zhu;password=12345");
foreach (Project p in ctx.GetTable
{
Console.WriteLine(p.PName);
}
5.Use Context to Translate DataReader
We can use DataContext to translate the DataReader to our objective type.
We create a static method:
static SqlDataReader GetProject(SqlConnection con)
{
con.Open();
SqlDataReader reader;
using (SqlCommand cmd = new SqlCommand("Select * from Project", con))
{
reader = cmd.ExecuteReader();
}
return reader;
}
In this case we can use:
MyDataContext mctx = new MyDataContext("server=myServer;Database=MyDB;User Id=Jie Zhu;password=12345");
foreach (Project p in mctx.Translate
{
Console.WriteLine(p.PPerson);
}
6.Use DataContext ExcuteQuery method
IEnumerable
foreach (Project p in ProjectCollection)
{
Console.WriteLine(p.PID);
}
7. Use DataContext SubmitChanges to Update Table
MyDataContext mctx = new MyDataContext("server=myServer;Database=MyDB;User Id=Jie Zhu;password=12345");
Project p1 = mctx.Projects.Single(p => p.PID == 2);
p1.PPerson = "Erica";
mctx.SubmitChanges();
After we know DataContext clearly here, we know the internal mechanism of Linq to Sql.
For example, we create a Linq to Sql class called MyDataClasses, after database configuration and Table dragging to the designer. It created corresponding DataContext and DataTable classes. You can look at MyDataClasses.designer.cs file.
Friday, December 10, 2010
Prevent Sql Injection
What is Sql Injection
Take the page log in as an example:
protected void Button1_Click(object sender, EventArgs e)
{
string cmdstr="Select Count(*) From Users Where Username = '" + UserName.Text + "' And Password = '" + Password.Text + "'";
int result = 0;
using (var conn = new SqlConnection(connect))
{
using (var cmd = new SqlCommand(cmdstr, conn))
{
conn.Open();
result = (int)cmd.ExecuteScalar();
}
}
if (result > 0)
{
Response.Redirect("LoggedIn.aspx");
}
else
{
Label1.Text = "Invalid credentials";
}
}
This kind of code is easy to be get sql injection to be hacked.
For example if a hacker input in the control Username text box the following text:
admin' --
Like the following:
In this case the cmdstr becomes like the following
The hacker bypass the password and use admin account. Here is a link on sql injection cheat sheet:
http://ferruh.mavituna.com/sql-injection-cheatsheet-oku/
In order to prevent Sql Injection, we have 3 method:
1. Use Parameterized Queries
2. Use Stored Procedure
3. Use Linq to Sql
Use Parameterized Queries:
The above code changed to be:
....
string query = "Select * From User Where UserName= @UserName and Password=@PassWord";
using (var conn = new SqlConnection(connect))
{
using (var cmd = new SqlCommand(query, conn))
{
cmd.Parameters.Add("@UserName", SqlDbType.VarChar);
cmd.Parameters["@UserName"].Value = UserName.Text.ToString();
cmd.Parameters.Add("@PassWord", SqlDbType.VarChar);
cmd.Parameters["@PassWord"].Value = PassWord.Text.ToString();
conn.Open()
...
For the Stored Procedure which as parameters, it the similar.
For the Linq to Sql, it need another topic.
Take the page log in as an example:
protected void Button1_Click(object sender, EventArgs e)
{
string cmdstr="Select Count(*) From Users Where Username = '" + UserName.Text + "' And Password = '" + Password.Text + "'";
int result = 0;
using (var conn = new SqlConnection(connect))
{
using (var cmd = new SqlCommand(cmdstr, conn))
{
conn.Open();
result = (int)cmd.ExecuteScalar();
}
}
if (result > 0)
{
Response.Redirect("LoggedIn.aspx");
}
else
{
Label1.Text = "Invalid credentials";
}
}
This kind of code is easy to be get sql injection to be hacked.
For example if a hacker input in the control Username text box the following text:
admin' --
Like the following:
In this case the cmdstr becomes like the following
The hacker bypass the password and use admin account. Here is a link on sql injection cheat sheet:
http://ferruh.mavituna.com/sql-injection-cheatsheet-oku/
In order to prevent Sql Injection, we have 3 method:
1. Use Parameterized Queries
2. Use Stored Procedure
3. Use Linq to Sql
Use Parameterized Queries:
The above code changed to be:
....
string query = "Select * From User Where UserName= @UserName and Password=@PassWord";
using (var conn = new SqlConnection(connect))
{
using (var cmd = new SqlCommand(query, conn))
{
cmd.Parameters.Add("@UserName", SqlDbType.VarChar);
cmd.Parameters["@UserName"].Value = UserName.Text.ToString();
cmd.Parameters.Add("@PassWord", SqlDbType.VarChar);
cmd.Parameters["@PassWord"].Value = PassWord.Text.ToString();
conn.Open()
...
For the Stored Procedure which as parameters, it the similar.
For the Linq to Sql, it need another topic.
Tuesday, December 7, 2010
Difference between override and new
the keyword "new" doesn't change the base class method, while the keyword "override" changes.
We have these code:
class Program
{
static void Main(string[] args)
{
DerivedClass dc = new DerivedClass();
BaseClass bc = new DerivedClass() as BaseClass;
dc.Print();
bc.Print();
}
}
public abstract class BaseClass
{
public virtual void Print()
{
Console.WriteLine("This is base class");
}
}
public class DerivedClass : BaseClass
{
public new void Print()
{
Console.WriteLine("This is derived class");
}
}
The running results are:
This is derived class
This is base class
while if we wrote code below:
class Program
{
static void Main(string[] args)
{
DerivedClass dc = new DerivedClass();
BaseClass bc = new DerivedClass() as BaseClass;
dc.Print();
bc.Print();
}
}
public abstract class BaseClass
{
public virtual void Print()
{
Console.WriteLine("This is base class");
}
}
public class DerivedClass : BaseClass
{
public override void Print()
{
Console.WriteLine("This is derived class");
}
}
The running results are:
This is derived class
This is derived class
We have these code:
class Program
{
static void Main(string[] args)
{
DerivedClass dc = new DerivedClass();
BaseClass bc = new DerivedClass() as BaseClass;
dc.Print();
bc.Print();
}
}
public abstract class BaseClass
{
public virtual void Print()
{
Console.WriteLine("This is base class");
}
}
public class DerivedClass : BaseClass
{
public new void Print()
{
Console.WriteLine("This is derived class");
}
}
The running results are:
This is derived class
This is base class
while if we wrote code below:
class Program
{
static void Main(string[] args)
{
DerivedClass dc = new DerivedClass();
BaseClass bc = new DerivedClass() as BaseClass;
dc.Print();
bc.Print();
}
}
public abstract class BaseClass
{
public virtual void Print()
{
Console.WriteLine("This is base class");
}
}
public class DerivedClass : BaseClass
{
public override void Print()
{
Console.WriteLine("This is derived class");
}
}
The running results are:
This is derived class
This is derived class
Thursday, December 2, 2010
C# 4.0 features -- dynamic typing(1)
For this article, I am going to write what I understand so far. When I have more knowledge on dynamic, I will write more.
We write a method:
public static int GetLength(dynamic myvar)
{
return myvar.Length;
}
The dynamic keyword represents an object which will be resolved in runtime.
so in the Main entry, if we have an string object, it has Length property, we can use:
string mystring="this is for test";
int i=GetLength(mystring);
And also for an array, string[] myarr=new string[3]{"Test","Dynamic","Typing"};
array also have:
int j=GetLength(myarr);
There is no compile time error and there is no run time error.
But if we use int, it doesn't have property Length; int a=5;
int k=GetLength(a);
There is no compile time error. But in the run time, the dynamic object is resolved to int variable, and it doesn't have Length property, there will come out exception.
I wrote the following test code:
public class MyClass1
{
public int Length;
}
public class MyClass2
{ }
class Program
{
static void Main(string[] args)
{
MyClass1 myClass1=new MyClass1(){Length=3};
Console.WriteLine(GetLength(myClass1));
MyClass2 myClass2 = new MyClass2();
Console.WriteLine(GetLength(myClass2));
}
public static int GetLength(dynamic myvar)
{
return myvar.Length;
}
}
The above code explain the dynamic object, the dynamic objects are resolved to myClass1 and myClass2 respectively in the run time. In the compile time, the is no problem at all, but as myClass2 doesn't have Length property, there will have run time exception for the part: GetLength(myClass2). It will say, "RuntimeBinder exception is unhandled" as below:
The difference between "dynamic" and "var" keywords:
var is type inference, the type is determined at compile time, that means the type is determined when we assign the value to var variable.
dynamic the type is resolved at runtime, that is the dynamic type will be replaced by the actual type in run time.
Why dynamic?
To my understanding, C# is a static programming language, it do type check at compile time to improve the performance. But dynamic language such as Python which determine the type at run time. .Net 4.0 has the dynamic language runtime(DLR) which let the C# code by pass compile time type checking. So DLR can be use to programming interop with the dynamic language.
It is useful when we don't know the types in some object such as COM objects and it use IDispatch doing late binding. So C# programming in COM objects which do late binding will also have interop, and we may need to use dynamic.
Developers may use System.Reflection to do the late binding, and dynamic will from programming language to allow late binding.
And when people work on XML/HTML DOM objects, when we don't know some object types, it is needed to use dynamic.
We write a method:
public static int GetLength(dynamic myvar)
{
return myvar.Length;
}
The dynamic keyword represents an object which will be resolved in runtime.
so in the Main entry, if we have an string object, it has Length property, we can use:
string mystring="this is for test";
int i=GetLength(mystring);
And also for an array, string[] myarr=new string[3]{"Test","Dynamic","Typing"};
array also have:
int j=GetLength(myarr);
There is no compile time error and there is no run time error.
But if we use int, it doesn't have property Length; int a=5;
int k=GetLength(a);
There is no compile time error. But in the run time, the dynamic object is resolved to int variable, and it doesn't have Length property, there will come out exception.
I wrote the following test code:
public class MyClass1
{
public int Length;
}
public class MyClass2
{ }
class Program
{
static void Main(string[] args)
{
MyClass1 myClass1=new MyClass1(){Length=3};
Console.WriteLine(GetLength(myClass1));
MyClass2 myClass2 = new MyClass2();
Console.WriteLine(GetLength(myClass2));
}
public static int GetLength(dynamic myvar)
{
return myvar.Length;
}
}
The above code explain the dynamic object, the dynamic objects are resolved to myClass1 and myClass2 respectively in the run time. In the compile time, the is no problem at all, but as myClass2 doesn't have Length property, there will have run time exception for the part: GetLength(myClass2). It will say, "RuntimeBinder exception is unhandled" as below:
The difference between "dynamic" and "var" keywords:
var is type inference, the type is determined at compile time, that means the type is determined when we assign the value to var variable.
dynamic the type is resolved at runtime, that is the dynamic type will be replaced by the actual type in run time.
Why dynamic?
To my understanding, C# is a static programming language, it do type check at compile time to improve the performance. But dynamic language such as Python which determine the type at run time. .Net 4.0 has the dynamic language runtime(DLR) which let the C# code by pass compile time type checking. So DLR can be use to programming interop with the dynamic language.
It is useful when we don't know the types in some object such as COM objects and it use IDispatch doing late binding. So C# programming in COM objects which do late binding will also have interop, and we may need to use dynamic.
Developers may use System.Reflection to do the late binding, and dynamic will from programming language to allow late binding.
And when people work on XML/HTML DOM objects, when we don't know some object types, it is needed to use dynamic.
Wednesday, December 1, 2010
Write a Custom Extension Method
Let's follow this tutorial to write a custom Extension method:
http://msdn.microsoft.com/en-us/library/bb311042.aspx
Notice:
1.The extension method is defined in another static class other than the "container" class.
2.The extension method should be accessible by the "container" class.
3.When define extension method, the method has first parameter: this "Container" Class Type and "Container" Class variable, and after that, there will follow the other parameters.
4. When use the extension method, the parameters are from the second parameters.
class Program
{
static void Main(string[] args)
{
Cat cat1 = new Cat("Coco", 3);
cat1.Meow(2);
}
}
public class Cat
{
public string Name{get;set;}
public int Age{get;set;}
public Cat(string name, int age) { Name = name; Age = age; }
}
public static class CatExtensions
{
public static void Meow(this Cat cat, int times)
{
for (int i = 0; i < times; i++)
{
Console.WriteLine(cat.Name+": Meow, I am "+cat.Age.ToString()+" years old");
}
}
}
The running result is like:
We will find extension method is very useful. I take some another examples,
eg.
public static class IntExtensions
{
public static double Seconds(this int i)
{
return ((double)i /1000);
}
}
when use this we can use 2.Second();
eg.
public static class StringExtensions
{
public static string ReverseString(this string str)
{
.....
}
}
Here is a good reference:
http://msdn.microsoft.com/en-us/vcsharp/bb905825.aspx
it tells how internally extension method works(it is compiled to a static method with ExtensionAttrible), and it also tells how it distinguish from normal instance method by visual studio intelligence.
In Summary, Extension Method is nothing new than the static method. The compiler changed the Extension method into static method when compile the code. But use extension method it make code easier to read, eg. when we use Linq.
http://msdn.microsoft.com/en-us/library/bb311042.aspx
Notice:
1.The extension method is defined in another static class other than the "container" class.
2.The extension method should be accessible by the "container" class.
3.When define extension method, the method has first parameter: this "Container" Class Type and "Container" Class variable, and after that, there will follow the other parameters.
4. When use the extension method, the parameters are from the second parameters.
class Program
{
static void Main(string[] args)
{
Cat cat1 = new Cat("Coco", 3);
cat1.Meow(2);
}
}
public class Cat
{
public string Name{get;set;}
public int Age{get;set;}
public Cat(string name, int age) { Name = name; Age = age; }
}
public static class CatExtensions
{
public static void Meow(this Cat cat, int times)
{
for (int i = 0; i < times; i++)
{
Console.WriteLine(cat.Name+": Meow, I am "+cat.Age.ToString()+" years old");
}
}
}
The running result is like:
We will find extension method is very useful. I take some another examples,
eg.
public static class IntExtensions
{
public static double Seconds(this int i)
{
return ((double)i /1000);
}
}
when use this we can use 2.Second();
eg.
public static class StringExtensions
{
public static string ReverseString(this string str)
{
.....
}
}
Here is a good reference:
http://msdn.microsoft.com/en-us/vcsharp/bb905825.aspx
it tells how internally extension method works(it is compiled to a static method with ExtensionAttrible), and it also tells how it distinguish from normal instance method by visual studio intelligence.
In Summary, Extension Method is nothing new than the static method. The compiler changed the Extension method into static method when compile the code. But use extension method it make code easier to read, eg. when we use Linq.
Use Linq Query and Extension Method two styles to get IEnumerable Collections
for example there is a IEnumerable Object, we take an Array as an example:
string [5] arr=new string[5]{"bolt","create","eat","bat","boat"};
Use normal Linq query, that is
var q=from str in arr
where str.StartWith("b")
order by str.Length
select str;
Here we get an IEnumerable q;
We can also use Extension method for the class which implements IEnumerable interface.
var q=arr.Where(str=>str.StartWith("b"))
.OrderBy(str=>str.Length);
Notice the extension method Where(), OrderBy(), the parameter should be an predefined delegate --Predicate to call a function with boolean returned value.
As we know, Predicate, Action, Func can all be written in lambda expression.
So use the extension method, the format should be like: arr.Where(str=>str.StartWith("b")).
Let's go to definition of Where extension method:
public static IEnumerable Where(this IEnumerable source, Func predicate);
string [5] arr=new string[5]{"bolt","create","eat","bat","boat"};
Use normal Linq query, that is
var q=from str in arr
where str.StartWith("b")
order by str.Length
select str;
Here we get an IEnumerable q;
We can also use Extension method for the class which implements IEnumerable interface.
var q=arr.Where(str=>str.StartWith("b"))
.OrderBy(str=>str.Length);
Notice the extension method Where(), OrderBy(), the parameter should be an predefined delegate --Predicate to call a function with boolean returned value.
As we know, Predicate, Action, Func can all be written in lambda expression.
So use the extension method, the format should be like: arr.Where(str=>str.StartWith("b")).
Let's go to definition of Where extension method:
public static IEnumerable
Anonymous Class if the variable order not the same, the class types are not the same
I do some test with Anonymous Class:
var s1 = new { Name = "Tom", age = 35 };
var s2 = new { Name = "Eric", age = 35 };
var s3 = new { Name = "Eric", age = 35 };
var s4 = new { age = 35, Name = "Eric" };
Debug.Assert(s1 == s2);
//s1==s2 returns false
Debug.Assert(s1.age == s2.age);
//s1.age == s2.age retuns true
Debug.Assert(s2 == s3);
//s2==s3 returns false
Debug.Assert(s3== s4);
//There will have compile error in this case, as s3, s4 the
//anonymous class, the member orders are differenct, s3,s4 are
//considered as different types, compiling error out
Debug.Assert(s2.GetType() == s2.GetType());
//s2.GetType() == s3.GetType() retuns true
Debug.Assert(s3.GetType() == s4.GetType());
//s3.GetType() == s4.GetType() returns false
var s1 = new { Name = "Tom", age = 35 };
var s2 = new { Name = "Eric", age = 35 };
var s3 = new { Name = "Eric", age = 35 };
var s4 = new { age = 35, Name = "Eric" };
Debug.Assert(s1 == s2);
//s1==s2 returns false
Debug.Assert(s1.age == s2.age);
//s1.age == s2.age retuns true
Debug.Assert(s2 == s3);
//s2==s3 returns false
Debug.Assert(s3== s4);
//There will have compile error in this case, as s3, s4 the
//anonymous class, the member orders are differenct, s3,s4 are
//considered as different types, compiling error out
Debug.Assert(s2.GetType() == s2.GetType());
//s2.GetType() == s3.GetType() retuns true
Debug.Assert(s3.GetType() == s4.GetType());
//s3.GetType() == s4.GetType() returns false
Tuesday, November 30, 2010
Automatically Implemented Properties for readonly case And Object Initializer -- Let's review the C# 3.0 feature
public class ReadOnlyPoint
{
public int X {get; private set;}
public int Y {get; private set;}
public ReadOnlyPoint(int x, int y){X=x; Y=y;}
}
notice the word "private".
We can also use public int X {get;} //new notes
And the for example there is a class Point, it has the default constructor and a second constructor take the variable x.
public class Point
{
public int X{get;set;}
public int Y{get;set;}
public Point {};
public Point(int x){X=x;}
}
When we initialize this object, we can use the default constructor like:
Point p1=new Point{X=3,Y=4};
or we can use the 2nd constructor:
Point p2=new Point(1){Y=3};
We can also get the intializer nested:
public Class Circle
{
public Point Origin{get;set;}
public int Radius{get;set;}
}
var myCircle=new Circle{Origin=new Point{X=2, Y=4}, Radius=3};
For the Collections or the class which implemented IEnumerable interface.
We can write://this is nothing new
List < Point> pointlst=new List< Point>{new Point{X=2, Y=4},
new Point{X=1,Y=5},
new Point{X=3,Y=7}};
{
public int X {get; private set;}
public int Y {get; private set;}
public ReadOnlyPoint(int x, int y){X=x; Y=y;}
}
notice the word "private".
We can also use public int X {get;} //new notes
And the for example there is a class Point, it has the default constructor and a second constructor take the variable x.
public class Point
{
public int X{get;set;}
public int Y{get;set;}
public Point {};
public Point(int x){X=x;}
}
When we initialize this object, we can use the default constructor like:
Point p1=new Point{X=3,Y=4};
or we can use the 2nd constructor:
Point p2=new Point(1){Y=3};
We can also get the intializer nested:
public Class Circle
{
public Point Origin{get;set;}
public int Radius{get;set;}
}
var myCircle=new Circle{Origin=new Point{X=2, Y=4}, Radius=3};
For the Collections or the class which implemented IEnumerable interface.
We can write://this is nothing new
List < Point> pointlst=new List< Point>{new Point{X=2, Y=4},
new Point{X=1,Y=5},
new Point{X=3,Y=7}};
Linq to XML for those XML Files with Large file size
There is issue when we create XDocument object using the code:
XDocument mydoc=XDocument.Load("myfile.xml");
When the xml file is with large file size, there will have memory out exception.
This is a notorious issue for XDocument class:
See: http://mtaulty.com/CommunityServer/blogs/mike_taultys_blog/archive/2007/09/08/9803.aspx
http://james.newtonking.com/archive/2007/12/11/linq-to-xml-over-large-documents.aspx
We follow the article, the concept is use
XmlReader xreader=XmlReader.Create("myfile.xml");
And create an IEnumerable type object using XmlReader, and use Linq to query this IEnumerable collection.
The code is:
using System.Xml;
using System.Xml.Linq;
class Program
{
static void Main(string[] args)
{
XNamespace myNS = XNamespace.Get("http://myns.xsd");
IEnumerable myElements = GetElements(@"myfile.xml", "product");
var q = from c in myElements
where (null != c.Element(myNS + "merchantListing").Element(myNS + "merchantProduct").Attribute("mid"))
select new { WebID = c.Attribute("id").Value.ToString() };
foreach (var item in q)
{
Console.WriteLine(item.WebID);
}
}
public static IEnumerable GetElements(string fileuri,string name)
{
using(XmlReader xreader=XmlReader.Create(fileuri))
{
xreader.MoveToContent();
while (xreader.Read())
{
if (xreader.NodeType == XmlNodeType.Element && xreader.Name ==name)
{
XElement element = (XElement)XElement.ReadFrom(xreader);
yield return element;
}
}
xreader.Close();
}
}
}
Here we use Linq to XML.
Of course, we don't necessary to "MUST" use Linq. As XDocument.Decendents("..."), this is IEnumerable type, we can use foreach as well.
XDocument myDoc=XDocument.Load("myfile.xml");
//for large size XML please use XMLReader as my previous post
XElement myel=myDoc.Decendent("product");
foreach(var item in myel)
{
Console.WriteLine(item.Element("id").Value);
}
XDocument mydoc=XDocument.Load("myfile.xml");
When the xml file is with large file size, there will have memory out exception.
This is a notorious issue for XDocument class:
See: http://mtaulty.com/CommunityServer/blogs/mike_taultys_blog/archive/2007/09/08/9803.aspx
http://james.newtonking.com/archive/2007/12/11/linq-to-xml-over-large-documents.aspx
We follow the article, the concept is use
XmlReader xreader=XmlReader.Create("myfile.xml");
And create an IEnumerable
The code is:
using System.Xml;
using System.Xml.Linq;
class Program
{
static void Main(string[] args)
{
XNamespace myNS = XNamespace.Get("http://myns.xsd");
IEnumerable
var q = from c in myElements
where (null != c.Element(myNS + "merchantListing").Element(myNS + "merchantProduct").Attribute("mid"))
select new { WebID = c.Attribute("id").Value.ToString() };
foreach (var item in q)
{
Console.WriteLine(item.WebID);
}
}
public static IEnumerable
{
using(XmlReader xreader=XmlReader.Create(fileuri))
{
xreader.MoveToContent();
while (xreader.Read())
{
if (xreader.NodeType == XmlNodeType.Element && xreader.Name ==name)
{
XElement element = (XElement)XElement.ReadFrom(xreader);
yield return element;
}
}
xreader.Close();
}
}
}
Here we use Linq to XML.
Of course, we don't necessary to "MUST" use Linq. As XDocument.Decendents("..."), this is IEnumerable type, we can use foreach as well.
XDocument myDoc=XDocument.Load("myfile.xml");
//for large size XML please use XMLReader as my previous post
XElement myel=myDoc.Decendent("product");
foreach(var item in myel)
{
Console.WriteLine(item.Element("id").Value);
}
Friday, November 19, 2010
Linq to XML for those XML Files which has namespace in it
For example I have a XML file myfile.xml
< ?xml version="1.0" encoding="utf-8"?>
< Products xmlns="http://mytest.xsd">
< Product id="1">
< name> myProduct < /name>
< /Product>
< /Products>
eg. in xsd file we know id is interger.
When we use Linq to XML to query this file, when dealing with XElement or XDecendents, the parameter should be Namespace+ElementName, The code is like below:
XNamespace myNS = XNamespace.Get("http://mytest.xsd");
XDocument myDoc = XDocument.Load(@"myfile.xml");
var query = from c in myDoc.Descendants(myNS + "product")
select new
{MyID=c.Attribute("id")!=null?c.Attribute("id").ToString():String.Empty,
MyName=c.Element(myNS+"name")!=null?MyName=c.Element(myNS+"name").ToString():String.Empty}
< ?xml version="1.0" encoding="utf-8"?>
< Products xmlns="http://mytest.xsd">
< Product id="1">
< name> myProduct < /name>
< /Product>
< /Products>
eg. in xsd file we know id is interger.
When we use Linq to XML to query this file, when dealing with XElement or XDecendents, the parameter should be Namespace+ElementName, The code is like below:
XNamespace myNS = XNamespace.Get("http://mytest.xsd");
XDocument myDoc = XDocument.Load(@"myfile.xml");
var query = from c in myDoc.Descendants(myNS + "product")
select new
{MyID=c.Attribute("id")!=null?c.Attribute("id").ToString():String.Empty,
MyName=c.Element(myNS+"name")!=null?MyName=c.Element(myNS+"name").ToString():String.Empty}
Thursday, November 18, 2010
Silverlight 4 and WCF RIA service (1)
There are some useful links here which we can follow by:
http://weblogs.asp.net/scottgu/archive/2010/05/17/silverlight-4-tools-for-vs-2010-and-wcf-ria-services-released.aspx
http://www.silverlightshow.net/items/WCF-RIA-Services-Part-1-Getting-Started.aspx
http://www.dotnetscraps.com/dotnetscraps/post/Silverlight-and-NET-RIA-Services-Step-by-Step-6.aspx
http://peterkellner.net/2010/01/20/riaservices-silverlight-4-tutorial-svcc-part1of7-introduction/
In 2008, I begin to use Silverlight 2 and ADO.net data service, see my previous articles in 2008. RIA service is pretty much the same concept, it is a WCF service which can let silverlight client side application doing Data layer manipulation.
And I will also write something based on my study and practice.
One thing that people are now doing the debate about silverlight vs html5 furture. silverlight comparing html5 need to install the plugin and problem with crossplat form and performance issue make it seems not that attractive comparing to the html5. But my personal opinion is not need to worry about this too much:
Silverlight belongs to C#/.net developers, and most .Net developer likes this as it seperate the view with C# code. Especially when introduced the MVVM pattern, this get the C# developer more confortbale in Web development.
Silverlight in many places is like a subset of WPF although they are different projects. For developer, SL and WPF are quite similiar in many places. Even SL is dead(I don't think this happens in years), the SL developer can switch to WPF easily.
The techniques comming along with SL such as RIA Service is also useful in ASP.net applications.
On the other hand, HTML5 is more client side code. As a .Net people, developer may not like HTML that much comparing to SL. Current comparing to SL, html5 doesn't have good developement tools. And it doesn't seperate the present layer to logic layer that good comparing to Silverlight. But this also point out a trend of web developement, for the developers the script languages are also important. If some one who is going to take the MCTS 70-515 web developement exam, this also shows Microsoft trend that JQuery library/ AJAX technology became more important than before for .Net web developers.
Now let take look at Silverlight 4 with WCF RIA service.
http://weblogs.asp.net/scottgu/archive/2010/05/17/silverlight-4-tools-for-vs-2010-and-wcf-ria-services-released.aspx
http://www.silverlightshow.net/items/WCF-RIA-Services-Part-1-Getting-Started.aspx
http://www.dotnetscraps.com/dotnetscraps/post/Silverlight-and-NET-RIA-Services-Step-by-Step-6.aspx
http://peterkellner.net/2010/01/20/riaservices-silverlight-4-tutorial-svcc-part1of7-introduction/
In 2008, I begin to use Silverlight 2 and ADO.net data service, see my previous articles in 2008. RIA service is pretty much the same concept, it is a WCF service which can let silverlight client side application doing Data layer manipulation.
And I will also write something based on my study and practice.
One thing that people are now doing the debate about silverlight vs html5 furture. silverlight comparing html5 need to install the plugin and problem with crossplat form and performance issue make it seems not that attractive comparing to the html5. But my personal opinion is not need to worry about this too much:
Silverlight belongs to C#/.net developers, and most .Net developer likes this as it seperate the view with C# code. Especially when introduced the MVVM pattern, this get the C# developer more confortbale in Web development.
Silverlight in many places is like a subset of WPF although they are different projects. For developer, SL and WPF are quite similiar in many places. Even SL is dead(I don't think this happens in years), the SL developer can switch to WPF easily.
The techniques comming along with SL such as RIA Service is also useful in ASP.net applications.
On the other hand, HTML5 is more client side code. As a .Net people, developer may not like HTML that much comparing to SL. Current comparing to SL, html5 doesn't have good developement tools. And it doesn't seperate the present layer to logic layer that good comparing to Silverlight. But this also point out a trend of web developement, for the developers the script languages are also important. If some one who is going to take the MCTS 70-515 web developement exam, this also shows Microsoft trend that JQuery library/ AJAX technology became more important than before for .Net web developers.
Now let take look at Silverlight 4 with WCF RIA service.
Table Variable in TSql
From Performance angle, Table variable is using less resources than temp table.
Declare @MyTable Table
( Name varchar(100), EmployeeNumb int)
Insert Into @MyTable(Name, EmployeeNumb) Values ('Jerry', 2)
Update @MyTable Set EmployeeNumb=EmployeeNumb*2
Declare @MyTable Table
( Name varchar(100), EmployeeNumb int)
Insert Into @MyTable(Name, EmployeeNumb) Values ('Jerry', 2)
Update @MyTable Set EmployeeNumb=EmployeeNumb*2
Monday, November 15, 2010
C# 4.0 new feature (2) --Optional Parameters and Named Parameters
For example:
class Program
{
static void Main(string[] args)
{
Console.WriteLine(Cal(5,b:20,c:30));
Console.WriteLine(Cal(5,20, d:false));
}
private static int Cal(int a, int b = 0, int c = 50, bool d = true)
{
int i = a + b - c;
int j = a - b + c;
if (d == true)
return i;
else
return j;
}
}
result:
-5 //true, 5+20-30
35 //false,5-20+50
Sometimes we need to consider matching rule:
The method is be called will be the fewest parameters and also the type should be matched.
forexample:
class Program
{
static void Main(string[] args)
{
Console.WriteLine(Add(5));
Console.WriteLine(Add(5,10));
}
private static int Add(int i)
{
return i+2;
}
private static int Add(int i,int j)
{
return i+j;
}
private static double Add(int i,double j)
{
return i+j+2.0;
}
result:
7
10
class Program
{
static void Main(string[] args)
{
Console.WriteLine(Cal(5,b:20,c:30));
Console.WriteLine(Cal(5,20, d:false));
}
private static int Cal(int a, int b = 0, int c = 50, bool d = true)
{
int i = a + b - c;
int j = a - b + c;
if (d == true)
return i;
else
return j;
}
}
result:
-5 //true, 5+20-30
35 //false,5-20+50
Sometimes we need to consider matching rule:
The method is be called will be the fewest parameters and also the type should be matched.
forexample:
class Program
{
static void Main(string[] args)
{
Console.WriteLine(Add(5));
Console.WriteLine(Add(5,10));
}
private static int Add(int i)
{
return i+2;
}
private static int Add(int i,int j)
{
return i+j;
}
private static double Add(int i,double j)
{
return i+j+2.0;
}
result:
7
10
Wednesday, November 10, 2010
Use BackgroundWorker (3)
In this artile, I am going to build a simple application which has a button which is to call the calculuation function in background. A progressbar which will show the background progress status. A cancel button which will cancel the background thread working.
We can build this application use Asp.net web application or Window form application or WPF application. As for asp.net there is no default progressbar control in visual studio tool box, there need us to create custom web control in order to show progressbar. So I am going to test use either Winform or WPF application.
For windows form application there is BackgroundWorker control in tool box, so I am going to demostrate how to use this control.
1. Create a winform application.
2. Drag the progressbar control, buttons. And BackgroundWorker control to the form. Like below:
I. Build Progress Bar showing the background calculation progress
In the code behind, after initialize the component, we set the status bar Min/Max values, and the backgroundworker support progressreport and support cancelling property.
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.WorkerSupportsCancellation = true;
progressBar1.Minimum=0;
progressBar1.Maximum=100;
In the designer, right click the Background control in the properties events window:
Double click the DoWork, ProgressChanged, RunWorkerCompleted. See the following picture:
In the code behind create the following code:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
}
Double click Button1, and generate code:
private void button1_Click(object sender, EventArgs e)
{
}
We add the line of the code to call the background thread working:
backgroundWorker1.RunWorkerAsync();
Let's add the following code in the above backgroundWorker1_DoWork method:
for (int i = 0; i <= 10; i++)
{
backgroundWorker1.ReportProgress(i*10);
Thread.Sleep(500);
}
And the code progressBar1.Value=e.ProgressPercentage; to backgroundWorker1_ProgressChanged. Add the code MessageBox.Show("Congradulations, Calculation Finished!"); to backgroundWorker1_RunWorkerCompleted method.
Now the code behind will be:
public partial class BackgroundWorkerExample : Form
{
public BackgroundWorkerExample()
{
InitializeComponent();
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.WorkerSupportsCancellation = true;
progressBar1.Minimum = 0;
progressBar1.Maximum = 100;
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 0; i <= 10; i++)
{
backgroundWorker1.ReportProgress(i * 10);
Thread.Sleep(500);
}
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
MessageBox.Show("Congradulations, Calculation Finished!");
}
private void button1_Click(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
}
}
When we compile this solution, our application support the status update on the background calculation. After calculation is done, there is a message box jump out saying "Congradulations, Calculation Finished!".
The running result is like the following picture:
II. Let the application support Async Cancellation
Double click the Button2 and create code behind:
private void button2_Click(object sender, EventArgs e)
{
}
Add the code backgroundWorker1.CancelAsync(); in the above block.
Change the code in backgroundWorker1_DoWork block to be:
for (int i = 0; i <= 10; i++)
{
if (backgroundWorker1.CancellationPending == true)
{
MessageBox.Show("Calculation Canceled!");
e.Cancel = true;
return;
}
backgroundWorker1.ReportProgress(i*10);
Thread.Sleep(500);
}
And change the code in backgroundWorker1_RunWorkerCompleted block to be:
if (!(e.Cancelled))
MessageBox.Show("Congradulations, Calculation Finished!");
else
MessageBox.Show("Due to Cancellation, Calculation isn't finished");
Rebuilt our solution, now our project support Async Cancellation. Like the picture below:
You can download my code at:
http://groups.google.com/group/jiezhu0815myfiles/web/WinformBackgroundWorkerReportProgress.rar
We can build this application use Asp.net web application or Window form application or WPF application. As for asp.net there is no default progressbar control in visual studio tool box, there need us to create custom web control in order to show progressbar. So I am going to test use either Winform or WPF application.
For windows form application there is BackgroundWorker control in tool box, so I am going to demostrate how to use this control.
1. Create a winform application.
2. Drag the progressbar control, buttons. And BackgroundWorker control to the form. Like below:
I. Build Progress Bar showing the background calculation progress
In the code behind, after initialize the component, we set the status bar Min/Max values, and the backgroundworker support progressreport and support cancelling property.
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.WorkerSupportsCancellation = true;
progressBar1.Minimum=0;
progressBar1.Maximum=100;
In the designer, right click the Background control in the properties events window:
Double click the DoWork, ProgressChanged, RunWorkerCompleted. See the following picture:
In the code behind create the following code:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
}
Double click Button1, and generate code:
private void button1_Click(object sender, EventArgs e)
{
}
We add the line of the code to call the background thread working:
backgroundWorker1.RunWorkerAsync();
Let's add the following code in the above backgroundWorker1_DoWork method:
for (int i = 0; i <= 10; i++)
{
backgroundWorker1.ReportProgress(i*10);
Thread.Sleep(500);
}
And the code progressBar1.Value=e.ProgressPercentage; to backgroundWorker1_ProgressChanged. Add the code MessageBox.Show("Congradulations, Calculation Finished!"); to backgroundWorker1_RunWorkerCompleted method.
Now the code behind will be:
public partial class BackgroundWorkerExample : Form
{
public BackgroundWorkerExample()
{
InitializeComponent();
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.WorkerSupportsCancellation = true;
progressBar1.Minimum = 0;
progressBar1.Maximum = 100;
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 0; i <= 10; i++)
{
backgroundWorker1.ReportProgress(i * 10);
Thread.Sleep(500);
}
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
MessageBox.Show("Congradulations, Calculation Finished!");
}
private void button1_Click(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
}
}
When we compile this solution, our application support the status update on the background calculation. After calculation is done, there is a message box jump out saying "Congradulations, Calculation Finished!".
The running result is like the following picture:
II. Let the application support Async Cancellation
Double click the Button2 and create code behind:
private void button2_Click(object sender, EventArgs e)
{
}
Add the code backgroundWorker1.CancelAsync(); in the above block.
Change the code in backgroundWorker1_DoWork block to be:
for (int i = 0; i <= 10; i++)
{
if (backgroundWorker1.CancellationPending == true)
{
MessageBox.Show("Calculation Canceled!");
e.Cancel = true;
return;
}
backgroundWorker1.ReportProgress(i*10);
Thread.Sleep(500);
}
And change the code in backgroundWorker1_RunWorkerCompleted block to be:
if (!(e.Cancelled))
MessageBox.Show("Congradulations, Calculation Finished!");
else
MessageBox.Show("Due to Cancellation, Calculation isn't finished");
Rebuilt our solution, now our project support Async Cancellation. Like the picture below:
You can download my code at:
http://groups.google.com/group/jiezhu0815myfiles/web/WinformBackgroundWorkerReportProgress.rar
Monday, November 8, 2010
Use BackgroundWorker (2)
Some of the advantages to use BackgroundWorker include:
1. We can report the background thread working process.
2. We can cancel the background process.
Now let's look into this.
Let's look into some more memebers of BackgroundWorker class:
Event handler:
ProgressChanged: The event occurs when Reportprogress method is called.
Method:
ReportProgress: The method raises the ProgressChanged event.The method has one int type parameter indicating the percentage of progress.(eg. 0-100);
Property:
WorkerReportsProgress: This property indicates whether the BackgroundWorker componet can report updates. Notice we should set this property to be true to report out progress status.
III. Background Thread Working Status Report
Let me write the sample code below:
using System;
using System.Threading;
using System.ComponentModel;
class Program
{
static BackgroundWorker myWorker = new BackgroundWorker();
static void Main(string[] args)
{
myWorker.DoWork += new DoWorkEventHandler(myWorker_DoWork);
myWorker.RunWorkerAsync();
myWorker.WorkerReportsProgress = true;
myWorker.ProgressChanged += new ProgressChangedEventHandler(myWorker_ProgressChanged);
Thread.Sleep(6000);
}
static void myWorker_ProgressChanged(object sender,
ProgressChangedEventArgs e)
{
Console.WriteLine(e.ProgressPercentage.ToString()+"% finished.");
}
static void myWorker_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 0; i <= 10; i++)
{
myWorker.ReportProgress(i * 10);
Thread.Sleep(500);
}
}
}
Notice the logic here, each time the ReportProgress method is called, it fires up the ProgressChanged event and pass the value i*10 to ProgressChangedEventArgs's ProgressPercentage property.
The running results shows like:
The code is at: http://groups.google.com/group/jiezhu0815myfiles/web/BackgroundWorkerProgressExample.rar
IV.Cancel Background Thread
Comparing to Threadpool, Backgroundworker provides easy manipulation to cancel the background thread.
Let's look at the following Memebers:
Method:
CancelAsync: This method request the cancellation of a pending background operation.
Property:
WorkerSupportsCancellation: This property indicates whether BackgroundWorker component support asynchronous cancellation. In order to use the CancelAsync method, this property need to be set to true.
CancellationPending: This property indicates whether the application has been requested to cancel the background thread. In method(long run calculation method) called by DoWork eventhandler, we judge whether this property is true. If this property is true, we set the DoworkEventArg e and set its Cancel property to be true and use keyword "return" to cancel the background working.
I wrote the code sample below:
using System;
using System.Threading;
using System.ComponentModel;
class Program
{
static BackgroundWorker myWorker = new BackgroundWorker();
static void Main(string[] args)
{
myWorker.DoWork += new DoWorkEventHandler(myWorker_DoWork);
myWorker.RunWorkerAsync();
Thread.Sleep(3000);
Console.WriteLine("Cancelling Background working...");
myWorker.WorkerSupportsCancellation = true;
myWorker.CancelAsync();
Console.Read();
}
static void myWorker_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 0; i <= 10; i++)
{
Console.WriteLine(i.ToString());
Thread.Sleep(500);
if (myWorker.CancellationPending == true)
{
e.Cancel = true;
Console.WriteLine("Background working cancelled.");
return;
}
}
}
}
The running result is like below:
The code is attached here:
http://groups.google.com/group/jiezhu0815myfiles/web/CancelBackgroundWorkerExample.rar
1. We can report the background thread working process.
2. We can cancel the background process.
Now let's look into this.
Let's look into some more memebers of BackgroundWorker class:
Event handler:
ProgressChanged: The event occurs when Reportprogress method is called.
Method:
ReportProgress: The method raises the ProgressChanged event.The method has one int type parameter indicating the percentage of progress.(eg. 0-100);
Property:
WorkerReportsProgress: This property indicates whether the BackgroundWorker componet can report updates. Notice we should set this property to be true to report out progress status.
III. Background Thread Working Status Report
Let me write the sample code below:
using System;
using System.Threading;
using System.ComponentModel;
class Program
{
static BackgroundWorker myWorker = new BackgroundWorker();
static void Main(string[] args)
{
myWorker.DoWork += new DoWorkEventHandler(myWorker_DoWork);
myWorker.RunWorkerAsync();
myWorker.WorkerReportsProgress = true;
myWorker.ProgressChanged += new ProgressChangedEventHandler(myWorker_ProgressChanged);
Thread.Sleep(6000);
}
static void myWorker_ProgressChanged(object sender,
ProgressChangedEventArgs e)
{
Console.WriteLine(e.ProgressPercentage.ToString()+"% finished.");
}
static void myWorker_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 0; i <= 10; i++)
{
myWorker.ReportProgress(i * 10);
Thread.Sleep(500);
}
}
}
Notice the logic here, each time the ReportProgress method is called, it fires up the ProgressChanged event and pass the value i*10 to ProgressChangedEventArgs's ProgressPercentage property.
The running results shows like:
The code is at: http://groups.google.com/group/jiezhu0815myfiles/web/BackgroundWorkerProgressExample.rar
IV.Cancel Background Thread
Comparing to Threadpool, Backgroundworker provides easy manipulation to cancel the background thread.
Let's look at the following Memebers:
Method:
CancelAsync: This method request the cancellation of a pending background operation.
Property:
WorkerSupportsCancellation: This property indicates whether BackgroundWorker component support asynchronous cancellation. In order to use the CancelAsync method, this property need to be set to true.
CancellationPending: This property indicates whether the application has been requested to cancel the background thread. In method(long run calculation method) called by DoWork eventhandler, we judge whether this property is true. If this property is true, we set the DoworkEventArg e and set its Cancel property to be true and use keyword "return" to cancel the background working.
I wrote the code sample below:
using System;
using System.Threading;
using System.ComponentModel;
class Program
{
static BackgroundWorker myWorker = new BackgroundWorker();
static void Main(string[] args)
{
myWorker.DoWork += new DoWorkEventHandler(myWorker_DoWork);
myWorker.RunWorkerAsync();
Thread.Sleep(3000);
Console.WriteLine("Cancelling Background working...");
myWorker.WorkerSupportsCancellation = true;
myWorker.CancelAsync();
Console.Read();
}
static void myWorker_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 0; i <= 10; i++)
{
Console.WriteLine(i.ToString());
Thread.Sleep(500);
if (myWorker.CancellationPending == true)
{
e.Cancel = true;
Console.WriteLine("Background working cancelled.");
return;
}
}
}
}
The running result is like below:
The code is attached here:
http://groups.google.com/group/jiezhu0815myfiles/web/CancelBackgroundWorkerExample.rar
Friday, November 5, 2010
Use BackgroundWorker (1)
There are different ways to create multi-threading tasks such as:
1. Asynchronized Model Programming(AMP), I had an article about this before.
2. Parallel Programming, this is aslo used a lot in my daily work such as do parallel downloading of something, I will write an artile on this sometime later.
3. Threadpool.QueueUserworkItem to call back. Use the Threadpool is a traditional way dealing multi-threads tasks.
4. Use BackgroundWorker.
Let's look at the memebers of a BackgroundWorker first:
Let's first look into two event handler:
DoWork: This event handler will call the code in a seperate thread, and the event is fired by calling RunWorkerAsync method.
RunWorkerCompleted: This event occures when background thread completed or cancelled. Or an exception is raised.
and the method called RunWorkerAsync:
RunWorkerAsync: This method will fire the DoWork event.
We can write a simple code sample like:
using System;
using System.Threading;
using System.ComponentModel;
class Program
{
static BackgroundWorker myWorker = new BackgroundWorker();
static void Main(string[] args)
{
myWorker.DoWork += new DoWorkEventHandler(myWorker_DoWork);
myWorker.RunWorkerAsync();
for (int i = 0; ; i++)
{
Console.WriteLine("Main Thread writes: {0}", i.ToString());
Thread.Sleep(1000);
}
}
static void myWorker_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 0; ; i++)
{
Console.WriteLine("Background Thread writes: {0}", i.ToString());
Thread.Sleep(500);
}
}
}
The following picture shows the running result:
I. Pass parameters from main thread to background thread:
The parameters can be passed from main thread to background thread through include the parater in RunWorkerAsync method. The parameter will be passed to the DoworkEventArgs in background.
Here we change the code a bit:
using System;
using System.Threading;
using System.ComponentModel;
class Program
{
static BackgroundWorker myWorker = new BackgroundWorker();
static void Main(string[] args)
{
string[] names = new string[2] { "Tom", "Jack" };
myWorker.DoWork += new DoWorkEventHandler(myWorker_DoWork);
myWorker.RunWorkerAsync(names);
for (int i = 0; ; i++)
{
Console.WriteLine("Main Thread writes: {0}", i.ToString());
Thread.Sleep(1000);
}
}
static void myWorker_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 0; ; i++)
{
Console.WriteLine("Hello, {0}. Background Thread writes: {1}", ((string[])(e.Argument))[0], i.ToString());
Thread.Sleep(500);
}
}
}
In the above code, we pass the array to the background thread and used the array element here, the result is like the following picture.
II. Pass the background thread running result to main thread
The background thread runing result can also be passed to the Result property of the RunWorkerCompletedEventArgs parameter.
We write code example below:
using System;
using System.Threading;
using System.ComponentModel;
class Program
{
static BackgroundWorker myWorker = new BackgroundWorker();
static object completedResult;
static void Main(string[] args)
{
string[] names = new string[2] { "Tom", "Jack" };
myWorker.DoWork += new DoWorkEventHandler(myWorker_DoWork);
myWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(myWorker_RunWorkerCompleted);
myWorker.RunWorkerAsync(names);
for (int i = 0;i<10; i++)
{
Console.WriteLine("Main Thread writes: {0}", i.ToString());
Thread.Sleep(2000);
}
Console.WriteLine("The Calculation result from the background thread is:");
Console.WriteLine(completedResult??completedResult.ToString());
Console.Read();
}
static void myWorker_DoWork(object sender, DoWorkEventArgs e)
{
Console.WriteLine("Hello, {0}. Now we begin to calculating...", ((string[])e.Argument)[0]);
e.Result = myCal();
}
static void myWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
completedResult = e.Result;
}
static int myCal()
{
int i = 0;
for (int j = 0; j < 10; j++)
{
i += j;
Thread.Sleep(500);
}
return i;
}
}
The running result is like the following:
The sample code is placed at:
http://groups.google.com/group/jiezhu0815myfiles/web/BackgroundWorkerDemo.rar
1. Asynchronized Model Programming(AMP), I had an article about this before.
2. Parallel Programming, this is aslo used a lot in my daily work such as do parallel downloading of something, I will write an artile on this sometime later.
3. Threadpool.QueueUserworkItem to call back. Use the Threadpool is a traditional way dealing multi-threads tasks.
4. Use BackgroundWorker.
Let's look at the memebers of a BackgroundWorker first:
Let's first look into two event handler:
DoWork: This event handler will call the code in a seperate thread, and the event is fired by calling RunWorkerAsync method.
RunWorkerCompleted: This event occures when background thread completed or cancelled. Or an exception is raised.
and the method called RunWorkerAsync:
RunWorkerAsync: This method will fire the DoWork event.
We can write a simple code sample like:
using System;
using System.Threading;
using System.ComponentModel;
class Program
{
static BackgroundWorker myWorker = new BackgroundWorker();
static void Main(string[] args)
{
myWorker.DoWork += new DoWorkEventHandler(myWorker_DoWork);
myWorker.RunWorkerAsync();
for (int i = 0; ; i++)
{
Console.WriteLine("Main Thread writes: {0}", i.ToString());
Thread.Sleep(1000);
}
}
static void myWorker_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 0; ; i++)
{
Console.WriteLine("Background Thread writes: {0}", i.ToString());
Thread.Sleep(500);
}
}
}
The following picture shows the running result:
I. Pass parameters from main thread to background thread:
The parameters can be passed from main thread to background thread through include the parater in RunWorkerAsync method. The parameter will be passed to the DoworkEventArgs in background.
Here we change the code a bit:
using System;
using System.Threading;
using System.ComponentModel;
class Program
{
static BackgroundWorker myWorker = new BackgroundWorker();
static void Main(string[] args)
{
string[] names = new string[2] { "Tom", "Jack" };
myWorker.DoWork += new DoWorkEventHandler(myWorker_DoWork);
myWorker.RunWorkerAsync(names);
for (int i = 0; ; i++)
{
Console.WriteLine("Main Thread writes: {0}", i.ToString());
Thread.Sleep(1000);
}
}
static void myWorker_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 0; ; i++)
{
Console.WriteLine("Hello, {0}. Background Thread writes: {1}", ((string[])(e.Argument))[0], i.ToString());
Thread.Sleep(500);
}
}
}
In the above code, we pass the array to the background thread and used the array element here, the result is like the following picture.
II. Pass the background thread running result to main thread
The background thread runing result can also be passed to the Result property of the RunWorkerCompletedEventArgs parameter.
We write code example below:
using System;
using System.Threading;
using System.ComponentModel;
class Program
{
static BackgroundWorker myWorker = new BackgroundWorker();
static object completedResult;
static void Main(string[] args)
{
string[] names = new string[2] { "Tom", "Jack" };
myWorker.DoWork += new DoWorkEventHandler(myWorker_DoWork);
myWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(myWorker_RunWorkerCompleted);
myWorker.RunWorkerAsync(names);
for (int i = 0;i<10; i++)
{
Console.WriteLine("Main Thread writes: {0}", i.ToString());
Thread.Sleep(2000);
}
Console.WriteLine("The Calculation result from the background thread is:");
Console.WriteLine(completedResult??completedResult.ToString());
Console.Read();
}
static void myWorker_DoWork(object sender, DoWorkEventArgs e)
{
Console.WriteLine("Hello, {0}. Now we begin to calculating...", ((string[])e.Argument)[0]);
e.Result = myCal();
}
static void myWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
completedResult = e.Result;
}
static int myCal()
{
int i = 0;
for (int j = 0; j < 10; j++)
{
i += j;
Thread.Sleep(500);
}
return i;
}
}
The running result is like the following:
The sample code is placed at:
http://groups.google.com/group/jiezhu0815myfiles/web/BackgroundWorkerDemo.rar
Tuesday, October 5, 2010
Sharepoint 12 - Javascript in sharepoint edit form(2)
Sometimes we may need to hidden a display field in edit form.
What I do is use getElementByID to get the node of specific node.
And for the form field, use parentNode.parentNode et al to get a specific TR node.
And use object.style.display="none" to hide the table row.
What I do is use getElementByID to get the node of specific node.
And for the form field, use parentNode.parentNode et al to get a specific TR node.
And use object.style.display="none" to hide the table row.
Wednesday, September 29, 2010
Sharepoint 11 - Javascript in sharepoint edit form(1)
During my work, in the sharepoint edit form, I want one field be composed from another 2 fields:
I have some explanation of why I did in this way instead of using Calculated field:
1. The purpose here is to build the client side scripts to get some field can be intelligent input. So the value shows on the page only and they are not stored in server side.
--username, currently the template is not easy to use and it jumps out a dialog and we may also change to intelligent input in this direction
2. Some fields are not avaliable to the calculated field such as look up fields, sometimes username et al.
3. We want to strictly get the values on form/page, retrieve from server may change the values.
4. In my following case, it provides a intelligent input. As long as the user don't change the scroll down selection items. The text will not changed. And the user can still changed the title as he want before storing the data by click "OK" button.
The step is:
Step 1: In the item editform display page, add 2 paramters to the URL: PageView=Shared&ToolPaneView=2
Step 2: Add the Content Editor Webparts
Step 3. I wrote code like:
< Script>
var e = document.getElementById('ctl00_m_g_c7e99c14_1b78_4b18_95db_a232d74a99f4_ctl00_ctl04_ctl01_ctl00_ctl00_ctl04_ctl00_Lookup');
var txt1= e.options[e.selectedIndex].innerText;
e.onchange=function(){myfunc()};
var ee = document.getElementById('ctl00_m_g_c7e99c14_1b78_4b18_95db_a232d74a99f4_ctl00_ctl04_ctl02_ctl00_ctl00_ctl04_ctl00_DropDownChoice');
var txt2= ee.options[ee.selectedIndex].innerText;
ee.onchange=function(){myfunc()};
var tbox = document.getElementById('ctl00_m_g_c7e99c14_1b78_4b18_95db_a232d74a99f4_ctl00_ctl04_ctl00_ctl00_ctl00_ctl04_ctl00_ctl00_TextField');
if (tbox)
{
tbox.value = txt1+'('+txt2+')';
}
function myfunc()
{
txt1= e.options[e.selectedIndex].innerText;
txt2= ee.options[ee.selectedIndex].innerText;
tbox.value = txt1+'('+txt2+')';
}
< /Script>
There is little issue with above code, as innertext of IE and FF are use different functions. We need change here.
We can write the function like the below to fix the issue.
function getObjInnerText (obj)
{
return (obj.innerText) ? obj.innerText : (obj.textContent) ? obj.textContent : "";
}
I have some explanation of why I did in this way instead of using Calculated field:
1. The purpose here is to build the client side scripts to get some field can be intelligent input. So the value shows on the page only and they are not stored in server side.
--username, currently the template is not easy to use and it jumps out a dialog and we may also change to intelligent input in this direction
2. Some fields are not avaliable to the calculated field such as look up fields, sometimes username et al.
3. We want to strictly get the values on form/page, retrieve from server may change the values.
4. In my following case, it provides a intelligent input. As long as the user don't change the scroll down selection items. The text will not changed. And the user can still changed the title as he want before storing the data by click "OK" button.
The step is:
Step 1: In the item editform display page, add 2 paramters to the URL: PageView=Shared&ToolPaneView=2
Step 2: Add the Content Editor Webparts
Step 3. I wrote code like:
< Script>
var e = document.getElementById('ctl00_m_g_c7e99c14_1b78_4b18_95db_a232d74a99f4_ctl00_ctl04_ctl01_ctl00_ctl00_ctl04_ctl00_Lookup');
var txt1= e.options[e.selectedIndex].innerText;
e.onchange=function(){myfunc()};
var ee = document.getElementById('ctl00_m_g_c7e99c14_1b78_4b18_95db_a232d74a99f4_ctl00_ctl04_ctl02_ctl00_ctl00_ctl04_ctl00_DropDownChoice');
var txt2= ee.options[ee.selectedIndex].innerText;
ee.onchange=function(){myfunc()};
var tbox = document.getElementById('ctl00_m_g_c7e99c14_1b78_4b18_95db_a232d74a99f4_ctl00_ctl04_ctl00_ctl00_ctl00_ctl04_ctl00_ctl00_TextField');
if (tbox)
{
tbox.value = txt1+'('+txt2+')';
}
function myfunc()
{
txt1= e.options[e.selectedIndex].innerText;
txt2= ee.options[ee.selectedIndex].innerText;
tbox.value = txt1+'('+txt2+')';
}
< /Script>
There is little issue with above code, as innertext of IE and FF are use different functions. We need change here.
We can write the function like the below to fix the issue.
function getObjInnerText (obj)
{
return (obj.innerText) ? obj.innerText : (obj.textContent) ? obj.textContent : "";
}
WPF(1) Use of PageFunction
Thursday, September 16, 2010
Passing Parameters in Pages and Asp.net State Management
I am going to do summary about the state management and pass parameters between pages in asp.net.
1. Use PreviousPage Property:
For example we have a button the property: PostBackUrl navigate to a sencond page, or a HyperLink or the first page use the Server.Transfer() method to open the sencond page. We want to pass the parameters in the first page to the 2nd page.
We can use the 2nd page's PreviousPage property. (2nd page has a label with name mylbl, and first page has a textbox name mytxt).
Code pretty much like:
mylbl.Text=(TextBox)PreviousPage.FindControl("mytxt").Text.
sometimes we place textbox in a panel(or some controls implemented INamingContainer), forexample our id for pane is mypanel.
We can use pretty much like:
Panel p=(Panel)PreviousPage.FindControl("mypanel");
TextBox tbox=p.FindControl("mytxt");
sometimes we can writh the previous page property in the page declaration, like:
< %@ PreviousPageType VirtualPath="~/.....aspx" % >
Notice one thing: Response.Redirect("sencondpage.aspx"), the PreviousPage property doesn't work here.
There are some client Side state management techniques can do parameters passing:
The advantage of the client side state management techniques is it stores the data in client side which will get server not that heavy burdon, the disadvantage is security.
Some techniques of statemanagement in client side are:
ViewState: but notice ViewState cannot pass parameters in the different pages, it can only pass the parameters in the same page.
ControlState and Hidden Field, they are like ViewState and cannot pass parameters across pages.
But for client side techniques, we can use cookie and querystring to pass parameters between different pages:
2. Cookie:
Code pretty much like:
Response.Cookie["txt"].Value=mytxt.Text.ToString(); //notice cookie value is string
We can also define expiration time for cookie,
Response.Cookie["txt"].Expires=System.DateTime.Now.AddDays(1);
in the sencond page:
mylbl.Text=Request.Cookie["txt"].Value;
But there are many bad things about cookie such as security issues.
3. Use QueryString.
In the first page:
Response.Redirect("~/Page2.aspx?para1="+mylbl.Txt.ToString()+"¶2=....",
In the 2nd page just use:
Request.QueryString["para1"] ...
there are also problems with QueryString such as length limitation et al.
There are also some state management object in server side, such as Session, Application, Cache. The good thing about the server side state management object is secure.
They can all be used to pass parameters between pages.
4. Session.
just the first page Session["txt"]=mytextbox.Text;
sencond page mylbl=Session["txt"].ToString();
Notice that session object is stored in server side, but session ID is stored in cookie. sometimes we use cookieless setting, we can set the session ID in querystring.
Session state can also be stored InProc(by default in server side), it can also be stored in StateServer(we can see there is an windows service called ASP.NET State Service, it runs the aspnet_state.exe), and it can be stored in SQLServer.
1. Use PreviousPage Property:
For example we have a button the property: PostBackUrl navigate to a sencond page, or a HyperLink or the first page use the Server.Transfer() method to open the sencond page. We want to pass the parameters in the first page to the 2nd page.
We can use the 2nd page's PreviousPage property. (2nd page has a label with name mylbl, and first page has a textbox name mytxt).
Code pretty much like:
mylbl.Text=(TextBox)PreviousPage.FindControl("mytxt").Text.
sometimes we place textbox in a panel(or some controls implemented INamingContainer), forexample our id for pane is mypanel.
We can use pretty much like:
Panel p=(Panel)PreviousPage.FindControl("mypanel");
TextBox tbox=p.FindControl("mytxt");
sometimes we can writh the previous page property in the page declaration, like:
< %@ PreviousPageType VirtualPath="~/.....aspx" % >
Notice one thing: Response.Redirect("sencondpage.aspx"), the PreviousPage property doesn't work here.
There are some client Side state management techniques can do parameters passing:
The advantage of the client side state management techniques is it stores the data in client side which will get server not that heavy burdon, the disadvantage is security.
Some techniques of statemanagement in client side are:
ViewState: but notice ViewState cannot pass parameters in the different pages, it can only pass the parameters in the same page.
ControlState and Hidden Field, they are like ViewState and cannot pass parameters across pages.
But for client side techniques, we can use cookie and querystring to pass parameters between different pages:
2. Cookie:
Code pretty much like:
Response.Cookie["txt"].Value=mytxt.Text.ToString(); //notice cookie value is string
We can also define expiration time for cookie,
Response.Cookie["txt"].Expires=System.DateTime.Now.AddDays(1);
in the sencond page:
mylbl.Text=Request.Cookie["txt"].Value;
But there are many bad things about cookie such as security issues.
3. Use QueryString.
In the first page:
Response.Redirect("~/Page2.aspx?para1="+mylbl.Txt.ToString()+"¶2=....",
In the 2nd page just use:
Request.QueryString["para1"] ...
there are also problems with QueryString such as length limitation et al.
There are also some state management object in server side, such as Session, Application, Cache. The good thing about the server side state management object is secure.
They can all be used to pass parameters between pages.
4. Session.
just the first page Session["txt"]=mytextbox.Text;
sencond page mylbl=Session["txt"].ToString();
Notice that session object is stored in server side, but session ID is stored in cookie. sometimes we use cookieless setting, we can set the session ID in querystring.
Session state can also be stored InProc(by default in server side), it can also be stored in StateServer(we can see there is an windows service called ASP.NET State Service, it runs the aspnet_state.exe), and it can be stored in SQLServer.
Thursday, September 9, 2010
Use ADO.net Transaction Object
Sometimes we need to use ADO.net Transaction object because if a sql command execute, it may fail and we don't want the application or database changes with error in halfway, and we want to set to the initial state before our sql command execute.
There are famous ACID properties for Transaction object.(Atomicity, Consistency, Isolation, Durability).
Here is a paper which use SqlTransaction dealing with SqlBulkCopy, it is a good article:
http://www.aspdotnetcodes.com/SqlBulkCopy_With_SqlTransaction.aspx
I make notes how to use SqlTransation object below, we can write code like:
string constr=@"...."
using (SqlConnection con=....)
{
con.Open();
using (SqlTransaction tran=con.BeginTransation())
{
try
{
using (SqlCommand cmd=con.CreateCommand())
{
cmd.Transaction=tran;
cmd.Execute....;
}
tran.Commit();
}
catch
{
tran.Rollback();
}
}
}
That is, if a command execute sucessfully, we use SqlTransation Commit() method, and if it failed, we use its Rollback() method to rollback the transaction.
There are famous ACID properties for Transaction object.(Atomicity, Consistency, Isolation, Durability).
Here is a paper which use SqlTransaction dealing with SqlBulkCopy, it is a good article:
http://www.aspdotnetcodes.com/SqlBulkCopy_With_SqlTransaction.aspx
I make notes how to use SqlTransation object below, we can write code like:
string constr=@"...."
using (SqlConnection con=....)
{
con.Open();
using (SqlTransaction tran=con.BeginTransation())
{
try
{
using (SqlCommand cmd=con.CreateCommand())
{
cmd.Transaction=tran;
cmd.Execute....;
}
tran.Commit();
}
catch
{
tran.Rollback();
}
}
}
That is, if a command execute sucessfully, we use SqlTransation Commit() method, and if it failed, we use its Rollback() method to rollback the transaction.
Use DataAdapter Update Table that doesn't have primary keys
If the Table has primary key, We just need to use the SqlCommandBuilder, and DataAdpter Update() method:
Here we create a table in sql server:
CREATE TABLE [dbo].[TestTable](
[First Name] [nvarchar](50) NOT NULL,
[Last Name] [nchar](50) NULL,
[Score] [int] NULL,
CONSTRAINT [PK_TestTable] PRIMARY KEY CLUSTERED
(
[First Name] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
And let's insert 2 records in the table:
Insert into TestTable Values ('JayNair', 'SomeLastName' 99);
Insert into TestTable Values ('Bala', 'AnotherLastName',99);
Notice the table has Primary key, so update the table is very simple, the sampe code is like following:
using System;
using System.Data;
using System.Data.SqlClient;
string constr = @"Data Source=myserver;Initial Catalog=mydb;User Id=jiezhu;Password=mypass;";
SqlConnection con = new SqlConnection(constr);
SqlCommand cmd = con.CreateCommand();
cmd.CommandText = "Select * from TestTable";
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataSet ds = new DataSet("MyDS");
SqlCommandBuilder brd = new SqlCommandBuilder(da);
da.Fill(ds, "MyTable");
ds.Tables["MyTable"].Rows[0]["Score"] = 95;
ds.Tables["MyTable"].Rows.Add("Jie", "Zhu", 88);
da.Update(ds, "MyTable");
Notice here, set PK at FirstName is not reasonable. Many times, we need to update a table which doesn't have primary key. But for DataAdpter, UpdateCommand, InsertCommand properties, they use PK to do update and Insert. So in order to manipulate the table which doesn't have primary key, we need to define the UpdateCommand and InsertCommand ourselves:
Let's remove PK in our table:
CREATE TABLE [dbo].[TestTable](
[First Name] [nvarchar](50) NOT NULL,
[Last Name] [nchar](50) NULL,
[Score] [int] NULL
) ON [PRIMARY]
And in our C# code, the complete code is like following:
using System;
using System.Data;
using System.Data.SqlClient;
string constr = @"Data Source=myserver;Initial Catalog=mydb;User Id=jiezhu;Password=mypass;";
SqlConnection con = new SqlConnection(constr);
SqlCommand cmd = con.CreateCommand();
cmd.CommandText = "Select * from TestTable";
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataSet ds = new DataSet("MyDS");
SqlCommandBuilder brd = new SqlCommandBuilder(da);
da.Fill(ds, "MyTable");
ds.Tables["MyTable"].Rows[0]["Score"] = 95;
ds.Tables["MyTable"].Rows.Add("Jie", "Zhu", 88);
da.UpdateCommand = new SqlCommand("UPDATE TestTable SET [First Name] = @FirstName, [Last Name] = @LastName, Score=@Score " +
"WHERE [First Name] = @FirstName and [Last Name] = @LastName", con);
da.UpdateCommand.Parameters.Add("@FirstName", SqlDbType.NChar, 50, "First Name");
da.UpdateCommand.Parameters.Add("@LastName", SqlDbType.NChar, 50, "Last Name");
da.UpdateCommand.Parameters.Add("@Score", SqlDbType.Int, 4, "Score");
da.InsertCommand = new SqlCommand("INSERT INTO TestTable ([First Name], [Last Name], Score) " +
"VALUES (@FirstName, @LastName, @Score)", con);
da.InsertCommand.Parameters.Add("@FirstName", SqlDbType.NChar, 50, "First Name");
da.InsertCommand.Parameters.Add("@LastName", SqlDbType.NChar, 50, "Last Name");
da.InsertCommand.Parameters.Add("@Score", SqlDbType.Int, 4, "Score");
da.Update(ds, "MyTable");
Here we create a table in sql server:
CREATE TABLE [dbo].[TestTable](
[First Name] [nvarchar](50) NOT NULL,
[Last Name] [nchar](50) NULL,
[Score] [int] NULL,
CONSTRAINT [PK_TestTable] PRIMARY KEY CLUSTERED
(
[First Name] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
And let's insert 2 records in the table:
Insert into TestTable Values ('JayNair', 'SomeLastName' 99);
Insert into TestTable Values ('Bala', 'AnotherLastName',99);
Notice the table has Primary key, so update the table is very simple, the sampe code is like following:
using System;
using System.Data;
using System.Data.SqlClient;
string constr = @"Data Source=myserver;Initial Catalog=mydb;User Id=jiezhu;Password=mypass;";
SqlConnection con = new SqlConnection(constr);
SqlCommand cmd = con.CreateCommand();
cmd.CommandText = "Select * from TestTable";
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataSet ds = new DataSet("MyDS");
SqlCommandBuilder brd = new SqlCommandBuilder(da);
da.Fill(ds, "MyTable");
ds.Tables["MyTable"].Rows[0]["Score"] = 95;
ds.Tables["MyTable"].Rows.Add("Jie", "Zhu", 88);
da.Update(ds, "MyTable");
Notice here, set PK at FirstName is not reasonable. Many times, we need to update a table which doesn't have primary key. But for DataAdpter, UpdateCommand, InsertCommand properties, they use PK to do update and Insert. So in order to manipulate the table which doesn't have primary key, we need to define the UpdateCommand and InsertCommand ourselves:
Let's remove PK in our table:
CREATE TABLE [dbo].[TestTable](
[First Name] [nvarchar](50) NOT NULL,
[Last Name] [nchar](50) NULL,
[Score] [int] NULL
) ON [PRIMARY]
And in our C# code, the complete code is like following:
using System;
using System.Data;
using System.Data.SqlClient;
string constr = @"Data Source=myserver;Initial Catalog=mydb;User Id=jiezhu;Password=mypass;";
SqlConnection con = new SqlConnection(constr);
SqlCommand cmd = con.CreateCommand();
cmd.CommandText = "Select * from TestTable";
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataSet ds = new DataSet("MyDS");
SqlCommandBuilder brd = new SqlCommandBuilder(da);
da.Fill(ds, "MyTable");
ds.Tables["MyTable"].Rows[0]["Score"] = 95;
ds.Tables["MyTable"].Rows.Add("Jie", "Zhu", 88);
da.UpdateCommand = new SqlCommand("UPDATE TestTable SET [First Name] = @FirstName, [Last Name] = @LastName, Score=@Score " +
"WHERE [First Name] = @FirstName and [Last Name] = @LastName", con);
da.UpdateCommand.Parameters.Add("@FirstName", SqlDbType.NChar, 50, "First Name");
da.UpdateCommand.Parameters.Add("@LastName", SqlDbType.NChar, 50, "Last Name");
da.UpdateCommand.Parameters.Add("@Score", SqlDbType.Int, 4, "Score");
da.InsertCommand = new SqlCommand("INSERT INTO TestTable ([First Name], [Last Name], Score) " +
"VALUES (@FirstName, @LastName, @Score)", con);
da.InsertCommand.Parameters.Add("@FirstName", SqlDbType.NChar, 50, "First Name");
da.InsertCommand.Parameters.Add("@LastName", SqlDbType.NChar, 50, "Last Name");
da.InsertCommand.Parameters.Add("@Score", SqlDbType.Int, 4, "Score");
da.Update(ds, "MyTable");
Tuesday, September 7, 2010
Use Multiple Active Result Sets(MARS) to Execute Multiple Commands on a Connection in ADO.net
In ADO.net, if you try to execute another command while the first command is executing,thre will have an InvalidOperationException: "There is already an open DataReader associated with this Connection which must be closed first".
We can use Mutilple Active Result Sets(MARS) to solve this issue.
The only change is in the connection string:
string constring=@"Data Source=....; MultipleActiveResultSets=True";
So in our code, we can write:
SqlConnection con=new SqlConnection(constring);
SqlCommand cmd1=....;
SqlCommand cmd2=...;
con.Open();
SqlDataReader reader=cmd1.ExecuteReader();
while(reader.Read())
{
cmd2.ExecuteScalar();
....
}
con.Close();
Notice that MARS will affect performace negatively. So if we don't need use MARS we shouldnot use it.
But in the following case MARS benefits:
1. Like the above example, if we don't use MARS, we open connection twice. That is we open the connection, loop the collection and read the results to a collection. Close the connection. Open the collection again do the second sqlcommand. If we don't use MARS we will loop the collection twice which is not efficient.
2. Some times it is expensive to create two connections. Some third party may charge twices for 2 connections.
We can use Mutilple Active Result Sets(MARS) to solve this issue.
The only change is in the connection string:
string constring=@"Data Source=....; MultipleActiveResultSets=True";
So in our code, we can write:
SqlConnection con=new SqlConnection(constring);
SqlCommand cmd1=....;
SqlCommand cmd2=...;
con.Open();
SqlDataReader reader=cmd1.ExecuteReader();
while(reader.Read())
{
cmd2.ExecuteScalar();
....
}
con.Close();
Notice that MARS will affect performace negatively. So if we don't need use MARS we shouldnot use it.
But in the following case MARS benefits:
1. Like the above example, if we don't use MARS, we open connection twice. That is we open the connection, loop the collection and read the results to a collection. Close the connection. Open the collection again do the second sqlcommand. If we don't use MARS we will loop the collection twice which is not efficient.
2. Some times it is expensive to create two connections. Some third party may charge twices for 2 connections.
Use the tool aspnet_regiis.exe to encrypt and decrypt connection string in web.config
We place connection string in web.config like:
< ?xml version="1.0"?>
< configuration xmlns="http..... ">
< appSettings/>
< connectionStrings>
< connectionStrings/>
< system.web>
...
< /system.web>
< /configration>
We can use Visual Studio Command prompt to run the following command to encrypt and decrypt connection string in web.config:
aspnet_regiis -pef "connectionStrings" "C:\....\EncryptWebSite"
aspnet_regiis -pdf "connectionStrings" "C:\....\EncryptWebSite"
< ?xml version="1.0"?>
< configuration xmlns="http..... ">
< appSettings/>
< connectionStrings>
< connectionStrings/>
< system.web>
...
< /system.web>
< /configration>
We can use Visual Studio Command prompt to run the following command to encrypt and decrypt connection string in web.config:
aspnet_regiis -pef "connectionStrings" "C:\....\EncryptWebSite"
aspnet_regiis -pdf "connectionStrings" "C:\....\EncryptWebSite"
ADO.net Connection Pool (2)
Something more about Connection Pool:
1. Connection Polling is the process of reusing existing active connections instead of creating new connections when a request is made to the database.
2. When the connection manager recieves a request for a new connection, it checks its pool for available connections. If a connection is available, it returns, if no connections available, and the maximum pool size has not been reached, a new connection is created and returned.
3. If the maximal connection pool size has been reached, the connection requested is added to the queue.
4. Minimal pool size default is 0. When your application requires consistence, sometimes we set this value to be 5 even the application is inactive for long period of time.
5. Maximal pool size default 100.
6. To implement connection pooling. The connection string must be exactly the same, case sensitive and even space in the string should be the same.
7. The user ID must be the same for every user or service in the pool.
8. The process ID must be the same, it is impossible to share connection across processes.
9. Where is pool located? Connection pool is a client side technology, which means the database doesn't know anything about the connection pools involved in your application.
10. When is pool created? When the first connection is instantiated, a connection pool group is created, but the first connection pool is not created until the first connection is opened.
1. Connection Polling is the process of reusing existing active connections instead of creating new connections when a request is made to the database.
2. When the connection manager recieves a request for a new connection, it checks its pool for available connections. If a connection is available, it returns, if no connections available, and the maximum pool size has not been reached, a new connection is created and returned.
3. If the maximal connection pool size has been reached, the connection requested is added to the queue.
4. Minimal pool size default is 0. When your application requires consistence, sometimes we set this value to be 5 even the application is inactive for long period of time.
5. Maximal pool size default 100.
6. To implement connection pooling. The connection string must be exactly the same, case sensitive and even space in the string should be the same.
7. The user ID must be the same for every user or service in the pool.
8. The process ID must be the same, it is impossible to share connection across processes.
9. Where is pool located? Connection pool is a client side technology, which means the database doesn't know anything about the connection pools involved in your application.
10. When is pool created? When the first connection is instantiated, a connection pool group is created, but the first connection pool is not created until the first connection is opened.
Thursday, September 2, 2010
StreamReader read txt file from a http link
using System;
using System.IO;
using System.Net;
WebRequest request = WebRequest.Create(url);
request.Credentials = new NetworkCredential("username", "password");
//if there is credential.
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
using (StreamReader sr
= new StreamReader(response.GetResponseStream()))
{
string tstr = sr.ReadToEnd();
......
}
using System.IO;
using System.Net;
WebRequest request = WebRequest.Create(url);
request.Credentials = new NetworkCredential("username", "password");
//if there is credential.
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
using (StreamReader sr
= new StreamReader(response.GetResponseStream()))
{
string tstr = sr.ReadToEnd();
......
}
Sort Multiple Columns of DataTable using DataView object
DataTable's View has Sort Property.
During my work, I want to build a gridview which has Datatable sorted by first column, and then the second column, and then the third column.
I write the code like following:
Drage a GridView Control to the desinger with name GridView1.
GridView1.AutoGenerateColumns = false;
BoundField bf1 = new BoundField();
bf1.HeaderText = "Company Name";
bf1.DataField = "Company Name";
GridView1.Columns.Add(bf1);
BoundField bf2 = new BoundField();
bf2.HeaderText = "First Name";
bf2.DataField = "First_Name";
GridView1.Columns.Add(bf2);
BoundField bf3 = new BoundField();
bf3.HeaderText = "Last Name";
bf3.DataField = "Last_Name";
GridView1.Columns.Add(bf3);
BoundField bf4 = new BoundField();
bf4.HeaderText = "Salary";
bf4.DataField = "Salary";
GridView1.Columns.Add(bf4);
//The above code to build a GridView can also written in page sources
DataTable dt = new DataTable();
dt.Columns.Add("Company Name");
dt.Columns.Add("First_Name");
dt.Columns.Add("Last_Name");
dt.Columns.Add("Salary");
dt.Columns["Salary"].DataType = typeof(int);
DataRow dr1 = dt.NewRow();
dr1["Company Name"] = "Microsoft";
dr1["First_Name"] = "John";
dr1["Last_Name"] = "Smith";
dr1["Salary"] = 700000;
dt.Rows.Add(dr1);
DataRow dr2 = dt.NewRow();
dr2["Company Name"] = "Google";
dr2["First_Name"] = "Jay";
dr2["Last_Name"] = "Wan";
dr2["Salary"] = 1000000;
dt.Rows.Add(dr2);
DataRow dr3 = dt.NewRow();
dr3["Company Name"] = "Microsoft";
dr3["First_Name"] = "Eric";
dr3["Last_Name"] = "White";
dr3["Salary"] = 750000;
dt.Rows.Add(dr3);
DataRow dr4 = dt.NewRow();
dr4["Company Name"] = "Apple";
dr4["First_Name"] = "Jessica";
dr4["Last_Name"] = "Black";
dr4["Salary"] = 800000;
dt.Rows.Add(dr4);
DataRow dr5 = dt.NewRow();
dr5["Company Name"] = "Apple";
dr5["First_Name"] = "Jessica";
dr5["Last_Name"] = "White";
dr5["Salary"] = 500000;
dt.Rows.Add(dr5);
DataRow dr6 = dt.NewRow();
dr6["Company Name"] = "Apple";
dr6["First_Name"] = "Jessica";
dr6["Last_Name"] = "White";
dr6["Salary"] = 1500000;
dt.Rows.Add(dr6);
dt.DefaultView.Sort = "Company Name ASC,First_Name ASC,Last_Name DESC,Salary DESC";
GridView1.DataSource = dt;
GridView1.DataBind();
The results is like:
Notice, the DataView has the RowFilter, RowStateFilter Properties.
We can add:
dt.DefaultView.RowFilter="First_Name like 'J%' and Salary>600000" to display the data which has the first name like 'J%' and Salary>600000.(It is T sql where clause).
During my work, I want to build a gridview which has Datatable sorted by first column, and then the second column, and then the third column.
I write the code like following:
Drage a GridView Control to the desinger with name GridView1.
GridView1.AutoGenerateColumns = false;
BoundField bf1 = new BoundField();
bf1.HeaderText = "Company Name";
bf1.DataField = "Company Name";
GridView1.Columns.Add(bf1);
BoundField bf2 = new BoundField();
bf2.HeaderText = "First Name";
bf2.DataField = "First_Name";
GridView1.Columns.Add(bf2);
BoundField bf3 = new BoundField();
bf3.HeaderText = "Last Name";
bf3.DataField = "Last_Name";
GridView1.Columns.Add(bf3);
BoundField bf4 = new BoundField();
bf4.HeaderText = "Salary";
bf4.DataField = "Salary";
GridView1.Columns.Add(bf4);
//The above code to build a GridView can also written in page sources
DataTable dt = new DataTable();
dt.Columns.Add("Company Name");
dt.Columns.Add("First_Name");
dt.Columns.Add("Last_Name");
dt.Columns.Add("Salary");
dt.Columns["Salary"].DataType = typeof(int);
DataRow dr1 = dt.NewRow();
dr1["Company Name"] = "Microsoft";
dr1["First_Name"] = "John";
dr1["Last_Name"] = "Smith";
dr1["Salary"] = 700000;
dt.Rows.Add(dr1);
DataRow dr2 = dt.NewRow();
dr2["Company Name"] = "Google";
dr2["First_Name"] = "Jay";
dr2["Last_Name"] = "Wan";
dr2["Salary"] = 1000000;
dt.Rows.Add(dr2);
DataRow dr3 = dt.NewRow();
dr3["Company Name"] = "Microsoft";
dr3["First_Name"] = "Eric";
dr3["Last_Name"] = "White";
dr3["Salary"] = 750000;
dt.Rows.Add(dr3);
DataRow dr4 = dt.NewRow();
dr4["Company Name"] = "Apple";
dr4["First_Name"] = "Jessica";
dr4["Last_Name"] = "Black";
dr4["Salary"] = 800000;
dt.Rows.Add(dr4);
DataRow dr5 = dt.NewRow();
dr5["Company Name"] = "Apple";
dr5["First_Name"] = "Jessica";
dr5["Last_Name"] = "White";
dr5["Salary"] = 500000;
dt.Rows.Add(dr5);
DataRow dr6 = dt.NewRow();
dr6["Company Name"] = "Apple";
dr6["First_Name"] = "Jessica";
dr6["Last_Name"] = "White";
dr6["Salary"] = 1500000;
dt.Rows.Add(dr6);
dt.DefaultView.Sort = "Company Name ASC,First_Name ASC,Last_Name DESC,Salary DESC";
GridView1.DataSource = dt;
GridView1.DataBind();
The results is like:
Notice, the DataView has the RowFilter, RowStateFilter Properties.
We can add:
dt.DefaultView.RowFilter="First_Name like 'J%' and Salary>600000" to display the data which has the first name like 'J%' and Salary>600000.(It is T sql where clause).
Monday, August 30, 2010
Use Button CommandName, CommandArgument Property to dynamically Call Button Command Events
Button Server Control has two types: submit and command. By default a button is a submit button which doesn't have commandname, commandArguments, and it has button.Click events as the default event. We can create command button using the following steps.
Create a Web Application, in the designer drag 4 buttons:
Set the CommandName Property to be: btn1Command, btn2Command, btn3Command, btn4Command. And CommandArgument to be: Asc, Desc, Upper, Lower.
The Source is like:
< body>
< id="form1" runat="server" method="post" action="Default.aspx">
< id="Button1" runat="server" commandname="btn1Command" text="NAsc" commandargument="Asc">
< id="Button2" runat="server" commandname="btn2Command" text="NDesc" commandargument="Desc">
< id="Button3" runat="server" commandname="btn3Command" text="LUpper" commandargument="Upper">
< id="Button4" runat="server" commandname="btn4Command" text="LLower" commandargument="Lower">
< /form>
< /body>
In the Events window, set these 4 buttons Command to be: Button_Command, double click, and write in the Button_Command Event the following code:
protected void Button_Command(object sender, CommandEventArgs e)
{
switch (e.CommandName)
{
case "btn1Command":
ShowNumbers(e.CommandArgument);
break;
case "btn2Command":
ShowNumbers(e.CommandArgument);
break;
case "btn3Command":
ShowLetters(e.CommandArgument);
break;
case "btn4Command":
ShowLetters(e.CommandArgument);
break;
}
}
And Write the ShowNumbers, ShowLetters Methods:
private void ShowNumbers(object commandArgument)
{
if (commandArgument.ToString() == "Asc")
{
Response.Write("123");
}
else if (commandArgument.ToString() == "Desc")
{
Response.Write("321");
}
}
private void ShowLetters(object commandArgument)
{
if (commandArgument.ToString() == "Upper")
{
Response.Write("AAA");
}
else if (commandArgument.ToString() == "Lower")
{
Response.Write("aaa");
}
}
Build the web application to test the button commands. The sample code is at:
http://groups.google.com/group/jiezhu0815myfiles/web/ButtonCommandSample.rar
Create a Web Application, in the designer drag 4 buttons:
Set the CommandName Property to be: btn1Command, btn2Command, btn3Command, btn4Command. And CommandArgument to be: Asc, Desc, Upper, Lower.
The Source is like:
< body>
< id="form1" runat="server" method="post" action="Default.aspx">
< id="Button1" runat="server" commandname="btn1Command" text="NAsc" commandargument="Asc">
< id="Button2" runat="server" commandname="btn2Command" text="NDesc" commandargument="Desc">
< id="Button3" runat="server" commandname="btn3Command" text="LUpper" commandargument="Upper">
< id="Button4" runat="server" commandname="btn4Command" text="LLower" commandargument="Lower">
< /form>
< /body>
In the Events window, set these 4 buttons Command to be: Button_Command, double click, and write in the Button_Command Event the following code:
protected void Button_Command(object sender, CommandEventArgs e)
{
switch (e.CommandName)
{
case "btn1Command":
ShowNumbers(e.CommandArgument);
break;
case "btn2Command":
ShowNumbers(e.CommandArgument);
break;
case "btn3Command":
ShowLetters(e.CommandArgument);
break;
case "btn4Command":
ShowLetters(e.CommandArgument);
break;
}
}
And Write the ShowNumbers, ShowLetters Methods:
private void ShowNumbers(object commandArgument)
{
if (commandArgument.ToString() == "Asc")
{
Response.Write("123");
}
else if (commandArgument.ToString() == "Desc")
{
Response.Write("321");
}
}
private void ShowLetters(object commandArgument)
{
if (commandArgument.ToString() == "Upper")
{
Response.Write("AAA");
}
else if (commandArgument.ToString() == "Lower")
{
Response.Write("aaa");
}
}
Build the web application to test the button commands. The sample code is at:
http://groups.google.com/group/jiezhu0815myfiles/web/ButtonCommandSample.rar
Wednesday, August 25, 2010
Array.Find(), Array.FindLast() and Array.FindAll()
static void Main(string[] args)
{
string[] arr = new string[5] { "tests", "Google", "good","yes","grey" };
Console.WriteLine(Array.Find(arr, StartwithG));
Console.WriteLine(Array.FindLast(arr, StartwithG));
string[] arrstartwithg = Array.FindAll(arr, StartwithG);
foreach (string str in arrstartwithg)
{
Console.WriteLine(str);
}
}
static bool StartwithG(string str)
{
if (str.ToLower().StartsWith("g"))
return true;
else return false;
}
{
string[] arr = new string[5] { "tests", "Google", "good","yes","grey" };
Console.WriteLine(Array.Find(arr, StartwithG));
Console.WriteLine(Array.FindLast(arr, StartwithG));
string[] arrstartwithg = Array.FindAll(arr, StartwithG);
foreach (string str in arrstartwithg)
{
Console.WriteLine(str);
}
}
static bool StartwithG(string str)
{
if (str.ToLower().StartsWith("g"))
return true;
else return false;
}
Compare Array has equalent element
string[] arr1=new string[3]{"a","b","c"}
string[] arr2=new string[3]{"a","b","c"}
arr1==arr2 //false
arr1.Equals(arr2) //false
arr1.SequenceEqual(arr2) //true
string[] arr2=new string[3]{"a","b","c"}
arr1==arr2 //false
arr1.Equals(arr2) //false
arr1.SequenceEqual(arr2) //true
Tuesday, August 24, 2010
Recall the Use of Delegate
1.Define delegate use function signature:
ex.
delegate string MyDelegate(int i);
public static vod Main(args[])
{
MyDelegate d=myFunc;
Console.WriteLine(d(5));
}
static string MyFunc(int a)
{
return a.ToString();
}
2. Use delegate to call back a function,
change the code MyDelegate d=myFunc to MyDelegate d=new MyDelegate(myFunc);
The code will be:
delegate string MyDelegate(int i);
public static vod Main(args[])
{
MyDelegate d=new MyDelegate(myFunc);
Console.WriteLine(d(5));
}
static string MyFunc(int a)
{
return a.ToString();
}
3. Multicast delegate:
delegate void MyDelegate(int i);
public static vod Main(args[])
{
MyDelegate d=(MyDelegate)myFunc1+(MyDelegate)myFunc2-(MyDelegate)myFunc1;
d(5);
}
static void MyFunc1(int a)
{
Console.WriteLine(a.ToString());
}
static string MyFunc2(int a)
{
Console.WriteLine("second function:"+a.ToString());
}
4. Delegate Chain:
delegate void MyDelegate(int i);
public static vod Main(args[])
{
MyDelegate[] ds= new MyDelegate[]{(MyDelegate)myFunc1,(MyDelegate)myFunc2};
MyDelegate d=(MyDelegate)Delegate.Combine(ds);
d(5);
}
static void MyFunc1(int a)
{
Console.WriteLine(a.ToString());
}
static string MyFunc2(int a)
{
Console.WriteLine("second function:"+a.ToString());
}
5. delegate call anonymous method:
delegate void MyDelegate(int myint);
static void Main(args[])
{
MyDelegate d=delegate(int i){Console.WriteLine(i.ToString());}
d(5);
}
delegate to call anonymous method can be represented as lambda expression, so we can also write the above code as:
delegate void MyDelegate(int myint);
static void Main(args[])
{
MyDelegate d=(int i)=>{Console.WriteLine(i.ToString());};
d(5);
}
ex.
delegate string MyDelegate(int i);
public static vod Main(args[])
{
MyDelegate d=myFunc;
Console.WriteLine(d(5));
}
static string MyFunc(int a)
{
return a.ToString();
}
2. Use delegate to call back a function,
change the code MyDelegate d=myFunc to MyDelegate d=new MyDelegate(myFunc);
The code will be:
delegate string MyDelegate(int i);
public static vod Main(args[])
{
MyDelegate d=new MyDelegate(myFunc);
Console.WriteLine(d(5));
}
static string MyFunc(int a)
{
return a.ToString();
}
3. Multicast delegate:
delegate void MyDelegate(int i);
public static vod Main(args[])
{
MyDelegate d=(MyDelegate)myFunc1+(MyDelegate)myFunc2-(MyDelegate)myFunc1;
d(5);
}
static void MyFunc1(int a)
{
Console.WriteLine(a.ToString());
}
static string MyFunc2(int a)
{
Console.WriteLine("second function:"+a.ToString());
}
4. Delegate Chain:
delegate void MyDelegate(int i);
public static vod Main(args[])
{
MyDelegate[] ds= new MyDelegate[]{(MyDelegate)myFunc1,(MyDelegate)myFunc2};
MyDelegate d=(MyDelegate)Delegate.Combine(ds);
d(5);
}
static void MyFunc1(int a)
{
Console.WriteLine(a.ToString());
}
static string MyFunc2(int a)
{
Console.WriteLine("second function:"+a.ToString());
}
5. delegate call anonymous method:
delegate void MyDelegate(int myint);
static void Main(args[])
{
MyDelegate d=delegate(int i){Console.WriteLine(i.ToString());}
d(5);
}
delegate to call anonymous method can be represented as lambda expression, so we can also write the above code as:
delegate void MyDelegate(int myint);
static void Main(args[])
{
MyDelegate d=(int i)=>{Console.WriteLine(i.ToString());};
d(5);
}
Func< T,Tresult> , Action< T> and Predicate< T>
There are many Pre-defined delegates in C#, such as eventhandler, Predicate.
Func and Action two pre-defined delegate:
The syntax for Funcion is:
public delegate TResult Func(
T arg
)
The syntax for Action is:
public delegate void Action< in T>(
T obj
)
So Func and Action are essentially a special delegate:
We can use: Func myfunc=delegate(T para){ //Some method return Tout;}
//delegate calling an anonymous method;
Action myAction=delegate(T para){ //somemethod return void;}
//delegate calling an anonymous method;
As well, lambda expression can be considered as a special delegate calling an anonymous method: on the "=>" left side is the parameters to input, on the "=>" right side is the method, if the method return void, the delegate is void and if the method returns some type, the delegate returns some type.
So we can write:
Fun myFunc=(T para)=>(//Some method returns Tout);
Action myAct=(T para)=>(//Some method return void);
Here is some examples:
Func myFunc= delegate(string s)
{
return s.ToUpper();
};
We can write as: Func myFunct= (string s)=>s.ToUpper();
Console.WriteLine(myFunct("This is a test for Func delegate"));
As well for Action:
Action myAction=delegate(string s)
{
Console.WriteLine(s);
}
We can also write as Action myAction=(string s)=>{Console.WriteLine(s)};
Test the above code:
myAction("This is a test for Action delegate");
Predicate is the same thing, except the function called return boolean, it can also be written lambda expression.
Func and Action two pre-defined delegate:
The syntax for Funcion is:
public delegate TResult Func
T arg
)
The syntax for Action is:
public delegate void Action< in T>(
T obj
)
So Func and Action are essentially a special delegate:
We can use: Func
//delegate calling an anonymous method;
Action
//delegate calling an anonymous method;
As well, lambda expression can be considered as a special delegate calling an anonymous method: on the "=>" left side is the parameters to input, on the "=>" right side is the method, if the method return void, the delegate is void and if the method returns some type, the delegate returns some type.
So we can write:
Fun
Action
Here is some examples:
Func
{
return s.ToUpper();
};
We can write as: Func
Console.WriteLine(myFunct("This is a test for Func delegate"));
As well for Action:
Action
{
Console.WriteLine(s);
}
We can also write as Action
Test the above code:
myAction("This is a test for Action delegate");
Predicate is the same thing, except the function called return boolean, it can also be written lambda expression.
Wednesday, August 18, 2010
Some of the Testing Tools
*****TestDriven.Net
--Open source, see www.testdriven.net
****AutoRunner
--For automatic testing
***BorlandSilkTest
***Fit/Fitnesse For .net
***IBM Rational Functional Tester
**Compuware TestPartner
--Open source, see www.testdriven.net
****AutoRunner
--For automatic testing
***BorlandSilkTest
***Fit/Fitnesse For .net
***IBM Rational Functional Tester
**Compuware TestPartner
Use Query String to pass values between pages
Example: http://...../form.aspx?param1=career¶m2=ride
First Page, Rediret page from text input:
private void ButtonSubmit_Click(object sender, eventArgs e)
{
Response.Redirect("form.aspx?param1="+this.Form.Text1.Text +"¶m2="
+this.Form.Text);
}
Second Read value from query string:
private void Page_Load(object sender, eventArgs e)
{
Text1.Text=Request.QueryString["Param1"];
Text2.Text=Request.QueryString["Param2"];
}
First Page, Rediret page from text input:
private void ButtonSubmit_Click(object sender, eventArgs e)
{
Response.Redirect("form.aspx?param1="+this.Form.Text1.Text +"¶m2="
+this.Form.Text);
}
Second Read value from query string:
private void Page_Load(object sender, eventArgs e)
{
Text1.Text=Request.QueryString["Param1"];
Text2.Text=Request.QueryString["Param2"];
}
ADO.net Connection Pool (1)
In ADO.net, if every time we perform a query, we create a new connection. Like the following:
//connection1
Sqlconnection sqlcon=new Sqlconnction();
sqlcon.ConnectionString = constring + "database = DB1;Integrated Security=true";
sqlcon.Open();
sqlcon.Close();
//connetion2
Sqlconnection sqlcon=new Sqlconnction();
sqlcon.ConnectionString = constring + "database = DB2;Integrated Security=true";
sqlcon.Open();
sqlcon.Close();
//connection1
Sqlconnection sqlcon=new Sqlconnction();
sqlcon.ConnectionString = constring + "database = DB1;Integrated Security=true";
sqlcon.Open();
sqlcon.Close();
//connection1
Sqlconnection sqlcon=new Sqlconnction();
sqlcon.ConnectionString = constring + "database = DB1;Uid=sa ;Pwd=password";
sqlcon.Open();
sqlcon.Close();
//connection2
Sqlconnection sqlcon=new Sqlconnction();
sqlcon.ConnectionString = constring + "database = DB2;Integrated Security=true";
sqlcon.Open();
sqlcon.Close();
If for every query or transation there create a new connection, this will waste the resources, as create new connection will take time, which will cause the query slow for users.
ADO.net has the connection pool mechanism. For the created connections, they are placed in the connection pool, the connection object can be used from the pool in stead of initialize a new connection object. After a specific of time period, if a connection is not used, it can be disposed.
The connection pool can be created by the sqlconnection string, pretty much like:
SqlConnection mySqlConnection =
new SqlConnection("server=(local)\\SQLEXPRESS;database=MyDatabase;Integrated Security=SSPI;" +
"max pool size=10;min pool size=5"
);
//connection1
Sqlconnection sqlcon=new Sqlconnction();
sqlcon.ConnectionString = constring + "database = DB1;Integrated Security=true";
sqlcon.Open();
sqlcon.Close();
//connetion2
Sqlconnection sqlcon=new Sqlconnction();
sqlcon.ConnectionString = constring + "database = DB2;Integrated Security=true";
sqlcon.Open();
sqlcon.Close();
//connection1
Sqlconnection sqlcon=new Sqlconnction();
sqlcon.ConnectionString = constring + "database = DB1;Integrated Security=true";
sqlcon.Open();
sqlcon.Close();
//connection1
Sqlconnection sqlcon=new Sqlconnction();
sqlcon.ConnectionString = constring + "database = DB1;Uid=sa ;Pwd=password";
sqlcon.Open();
sqlcon.Close();
//connection2
Sqlconnection sqlcon=new Sqlconnction();
sqlcon.ConnectionString = constring + "database = DB2;Integrated Security=true";
sqlcon.Open();
sqlcon.Close();
If for every query or transation there create a new connection, this will waste the resources, as create new connection will take time, which will cause the query slow for users.
ADO.net has the connection pool mechanism. For the created connections, they are placed in the connection pool, the connection object can be used from the pool in stead of initialize a new connection object. After a specific of time period, if a connection is not used, it can be disposed.
The connection pool can be created by the sqlconnection string, pretty much like:
SqlConnection mySqlConnection =
new SqlConnection("server=(local)\\SQLEXPRESS;database=MyDatabase;Integrated Security=SSPI;" +
"max pool size=10;min pool size=5"
);
Monday, August 16, 2010
C# 4.0 Feature (1) Concurrent Collections
Before C# 4.0 comming out, there is no concurrent collections. So there is thread safety issue about the collections if mutiple thread access these collections.
Traditional way we do is lock the collection's syncroot property.
For example:
Hashtable ht=new Hashtable();
lock (ht.SyncRoot)
{
...//do somthing
}
Notice that the lock of "this" (lock(this)). or lock of an object instance is not a thread safe method. And Syncronized method is not thread safe for collections as well.
After C# 4.0 comming out, there is a new data structure: Concurrent Collection, and this data type makes thread safe.
We write an sample code below to use Concurrent Collection:
using System;
using System.Net;
using System.Threading.Tasks;
using System.Collections.Concurrent;
class Program
{
static void Main(string[] args)
{
var links = new ConcurrentQueue();
links.Enqueue("http://....aa.jpg");
links.Enqueue("http://....bb.jpg");
links.Enqueue("http://....cc.jpg");
Parallel.For(0, links.Count, delegate(int i)
{
string url;
string filename = "Product"+i + "test.jpg";
if (links.TryDequeue(out url))
{
DownLoad(url, filename);
}
});
}
private static void DownLoad(string url,string filename)
{
using (WebClient wc = new WebClient())
{
wc.DownloadFile(url, filename);
}
}
}
For the other Concurrent Data Type, such as ConcurrentBag, ConcurrentStack, ConcurrentList, please check msdn for use.
Traditional way we do is lock the collection's syncroot property.
For example:
Hashtable ht=new Hashtable();
lock (ht.SyncRoot)
{
...//do somthing
}
Notice that the lock of "this" (lock(this)). or lock of an object instance is not a thread safe method. And Syncronized method is not thread safe for collections as well.
After C# 4.0 comming out, there is a new data structure: Concurrent Collection, and this data type makes thread safe.
We write an sample code below to use Concurrent Collection:
using System;
using System.Net;
using System.Threading.Tasks;
using System.Collections.Concurrent;
class Program
{
static void Main(string[] args)
{
var links = new ConcurrentQueue
links.Enqueue("http://....aa.jpg");
links.Enqueue("http://....bb.jpg");
links.Enqueue("http://....cc.jpg");
Parallel.For(0, links.Count, delegate(int i)
{
string url;
string filename = "Product"+i + "test.jpg";
if (links.TryDequeue(out url))
{
DownLoad(url, filename);
}
});
}
private static void DownLoad(string url,string filename)
{
using (WebClient wc = new WebClient())
{
wc.DownloadFile(url, filename);
}
}
}
For the other Concurrent Data Type, such as ConcurrentBag, ConcurrentStack, ConcurrentList, please check msdn for use.
Wednesday, August 11, 2010
Integrate Microsoft BizTalk/TIBCO with Sharepoint
BizTalk or TIBCO as the midware is currently very hot. And the instant message system can make our job live. For my current work, we have ticket system, but those are pretty static and not instant communicate with client. BizTalk or TIBCO as a hot midware use Service Oriented Architecture, and seems a hot tool to improve our job. For example we can have the instant request from the client and we can have the instant message in the company use as well.
During my work on Sharepoint, to my feeling, Sharepoint is like a "container", it can host workflow, sql server reporting service, silverlight controls et al. But to costomize some of the forms/web parts is very annoying. After watching Microsoft introduction (http://www.microsoft.com/biztalk/en/us/click-through-demo/hol.htm),we can find combine sharepoint with BizTalk or TIBCO is more than just a "fancy" technique but very useful here.
But currently the tutorial on intergrate BizTalk/TIBCO is very few. In the near future in my spare time, I would do some research on this field and may keep posting some series on what I figure out.
During my work on Sharepoint, to my feeling, Sharepoint is like a "container", it can host workflow, sql server reporting service, silverlight controls et al. But to costomize some of the forms/web parts is very annoying. After watching Microsoft introduction (http://www.microsoft.com/biztalk/en/us/click-through-demo/hol.htm),we can find combine sharepoint with BizTalk or TIBCO is more than just a "fancy" technique but very useful here.
But currently the tutorial on intergrate BizTalk/TIBCO is very few. In the near future in my spare time, I would do some research on this field and may keep posting some series on what I figure out.
Wednesday, July 28, 2010
Sharepoint 10 - Restore job-immediate-alerts Job Definition in farm for a site
stsadm -o setproperty -propertyname "job-immediate-alerts" -url "http://sharepoint" -propertyvalue "every 1 minutes between 0 and 59"
Some times we need to get the property value:
stsadm -o getproperty -pn alerts-enabled -url http://sharepoint
Some times we need to get the property value:
stsadm -o getproperty -pn alerts-enabled -url http://sharepoint
Wednesday, July 21, 2010
SharePoint 9 -Some Useful Tool
1.
U2U CAML Query Builder
http://www.u2u.be/res/tools/camlquerybuilder.aspx
http://www.u2u.info/Blogs/Patrick/Lists/Posts/Post.aspx?ID=1252
2. Event Reciever Explorer.
U2U CAML Query Builder
http://www.u2u.be/res/tools/camlquerybuilder.aspx
http://www.u2u.info/Blogs/Patrick/Lists/Posts/Post.aspx?ID=1252
2. Event Reciever Explorer.
Tuesday, July 13, 2010
Synchronization Contexts
Synchronization Contexts provide a mechanism to lock declaratively/Automatically.
ex:
using System;
using System.Threading;
using System.Runtime.Remoting.Contexts;
[Synchronization]
public class MyLock:ContextBoundObject
{
public void DoSomething()
{
//do something....
}
}
public class MyTestClass
{
public static void Main()
{
MyLock instance=new MyLock();
new Thread(instance.DoSomething).Start();
new Thread(instance.DoSomething).Start();
instance.DoSomething();
}
}
ex:
using System;
using System.Threading;
using System.Runtime.Remoting.Contexts;
[Synchronization]
public class MyLock:ContextBoundObject
{
public void DoSomething()
{
//do something....
}
}
public class MyTestClass
{
public static void Main()
{
MyLock instance=new MyLock();
new Thread(instance.DoSomething).Start();
new Thread(instance.DoSomething).Start();
instance.DoSomething();
}
}
Friday, June 25, 2010
Path.Combine()
using System.IO;
string filePath = Path.Combine(
errorPath,
string.Format(“{0:MMddyyyyhhmmss}.png”, DateTime.Now)
);
string filePath = Path.Combine(
errorPath,
string.Format(“{0:MMddyyyyhhmmss}.png”, DateTime.Now)
);
Wednesday, May 12, 2010
Sharepoint 8 - Some Useful Webpart from Codeplex
1. Forum:
http://spforums.codeplex.com/releases/view/53
The installation instruction in wss 3.0 is:
Until we get the WSS 3.0/MOSS version available to you, ProgramPhases.com has put together an excellent article on setting up the web part on WSS 3.0.
You can find their instructions here on the site.
Here are the steps reproduced in case the site isn't available. I haven't verified these to work but some people say it does. HTH.
Installing Sharepoint Forums 1.2 support in WSS3 includes the following steps:
Install ASP.NET AJAX 1.0 for WSS3
Download and Install Sharepoint Forums 1.2
Add Custom JavaScript Code to the default.master Page
Add the Sharepoint Forums 1.2 Web Part to a Sharepoint Page
The instructions for installing ASP.NET AJAX 1.0 support in WSS3 can be found here.
Download the latest version of the forums from the releases tab here.
After downloading Sharepoint Forums 1.2, install using the provided setup program.
Open a command prompt and run the following command from the
C:\Program Files\WPPackager\{14aa60ab-2b6b-4254-b45e-0ef7b8b2a201} folder:
stsadm.exe -o addwppack -filename "SharePointForums-1.2.0.0_Bil Simser.cab" -globalinstall -force
Edit the default.master file using Office Sharepoint Designer 2007. Put following JavaScript code immediately before the ending < /body> tag in the file.
< script type="text/javascript">
function ProcessOwsForm(ctl, argument)
{
if (frm.fPreviewMode)
{
var LcantSaveText = "This form cannot be saved when previewing this page.";
window.alert(LcantSaveText);
return;
}
if (frm.FValidate(true))
{
frm.FPostProcess();
var theForm = document.forms['aspnetForm'];
__doPostBack2(ctl, argument);
}
}
function __doPostBack2(eventTarget, eventArgument)
{
theForm.__EVENTTARGET.value = eventTarget;
theForm.__EVENTARGUMENT.value = eventArgument;
theForm.submit();
}
< /script>
2. List Form
http://officetoolbox.codeplex.com/releases/view/15713
Download OfficeToolbox.SharePoint.Lists v1.0 from Codeplex or at SharePoint Toolbox at MSDN Code. Unzip the archive and run Setup.exe on your Server box where you want to install or try. Go to "Central Admin > Application Management > Manage Web Application Features" and activate the Feature.
3. Filtered Lookup
http://filteredlookup.codeplex.com/
http://spforums.codeplex.com/releases/view/53
The installation instruction in wss 3.0 is:
Until we get the WSS 3.0/MOSS version available to you, ProgramPhases.com has put together an excellent article on setting up the web part on WSS 3.0.
You can find their instructions here on the site.
Here are the steps reproduced in case the site isn't available. I haven't verified these to work but some people say it does. HTH.
Installing Sharepoint Forums 1.2 support in WSS3 includes the following steps:
Install ASP.NET AJAX 1.0 for WSS3
Download and Install Sharepoint Forums 1.2
Add Custom JavaScript Code to the default.master Page
Add the Sharepoint Forums 1.2 Web Part to a Sharepoint Page
The instructions for installing ASP.NET AJAX 1.0 support in WSS3 can be found here.
Download the latest version of the forums from the releases tab here.
After downloading Sharepoint Forums 1.2, install using the provided setup program.
Open a command prompt and run the following command from the
C:\Program Files\WPPackager\{14aa60ab-2b6b-4254-b45e-0ef7b8b2a201} folder:
stsadm.exe -o addwppack -filename "SharePointForums-1.2.0.0_Bil Simser.cab" -globalinstall -force
Edit the default.master file using Office Sharepoint Designer 2007. Put following JavaScript code immediately before the ending < /body> tag in the file.
< script type="text/javascript">
function ProcessOwsForm(ctl, argument)
{
if (frm.fPreviewMode)
{
var LcantSaveText = "This form cannot be saved when previewing this page.";
window.alert(LcantSaveText);
return;
}
if (frm.FValidate(true))
{
frm.FPostProcess();
var theForm = document.forms['aspnetForm'];
__doPostBack2(ctl, argument);
}
}
function __doPostBack2(eventTarget, eventArgument)
{
theForm.__EVENTTARGET.value = eventTarget;
theForm.__EVENTARGUMENT.value = eventArgument;
theForm.submit();
}
< /script>
2. List Form
http://officetoolbox.codeplex.com/releases/view/15713
Download OfficeToolbox.SharePoint.Lists v1.0 from Codeplex or at SharePoint Toolbox at MSDN Code. Unzip the archive and run Setup.exe on your Server box where you want to install or try. Go to "Central Admin > Application Management > Manage Web Application Features" and activate the Feature.
3. Filtered Lookup
http://filteredlookup.codeplex.com/
Thursday, May 6, 2010
Sharepoint 7 - Retrieve URL from SPListItem
Use the following:
SPFieldUrlValue fieldValue=new SPFieldUrlValue(myItem["URL"].ToString());
string LinkDescription=fieldValue.Description;
string LinkUrl=field.Url;
SPFieldUrlValue fieldValue=new SPFieldUrlValue(myItem["URL"].ToString());
string LinkDescription=fieldValue.Description;
string LinkUrl=field.Url;
Tuesday, May 4, 2010
Sharepoint 6 - Web Part Verbs
We need to override the Verbs property of Web Part, change the following code:
public override WebPartVerbCollection Verbs
{
get
{
return base.Verbs;
}
}
Change the code to be like
public override WebPartVerbCollection Verbs
{
get
{
List< WebPartVerb> newVerbs=new List< WebPartVerb>();
WebPartVerb verb1=new WebPartVerb(this.ID+"verb1", new WebPartEventHandler(ServerSideHandler));
verb1.Text="....";
verb1.Visible=true;
verb1.Description="....verb1";
newVerbs.Add(verb1);
WebPartVerb verb2=new WebPartVerb(this.ID+"verb2","alert('verb2');");
verb.Text="...";
...
newVerbs.Add(verb2);
WebPartVerbCollection myVerbs=new WebPartVerbCollection(base.Verbs, newVerbs);
return myVerbs;
}
}
public void ServerSideVerbHandler(object sender, WebPartEventArgs e){...}
public override WebPartVerbCollection Verbs
{
get
{
return base.Verbs;
}
}
Change the code to be like
public override WebPartVerbCollection Verbs
{
get
{
List< WebPartVerb> newVerbs=new List< WebPartVerb>();
WebPartVerb verb1=new WebPartVerb(this.ID+"verb1", new WebPartEventHandler(ServerSideHandler));
verb1.Text="....";
verb1.Visible=true;
verb1.Description="....verb1";
newVerbs.Add(verb1);
WebPartVerb verb2=new WebPartVerb(this.ID+"verb2","alert('verb2');");
verb.Text="...";
...
newVerbs.Add(verb2);
WebPartVerbCollection myVerbs=new WebPartVerbCollection(base.Verbs, newVerbs);
return myVerbs;
}
}
public void ServerSideVerbHandler(object sender, WebPartEventArgs e){...}
Wednesday, April 21, 2010
Sharepint 5 - Use SPJobDefinition to schedule a Job
Build a Console Application, reference Microsoft.Sharepoint.dll
Ex 1. If we want to get all the scheduled jobs in a site:
using System;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
class Program
{
static void Main(string[] args)
{
SPSite mySite = new SPSite("http://mysite:port");
foreach (SPJobDefinition job in
mySite.WebApplication.JobDefinitions)
{
Console.WriteLine("JobName: {0} , Last Run time: {1}, Type: {2}",job .Title,job.LastRunTime.ToLongTimeString(),job.Schedule.GetType().ToString()));
}
}
}
Ex 2. If we want to delete a scheduled job.
using System;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
class Program
{
static void Main(string[] args)
{
SPSite mySite = new SPSite("http://mysite:port");
foreach (SPJobDefinition job in
mySite.WebApplication.JobDefinitions)
{
if(job.Title=="My Job")
{job.Delete();}
}
}
}
Ex 3. Now let's talk about Create a Job, and Register and Schedule it.
Create a Console Application, reference Microsoft.Sharepoint.dll, Add a new item class, call this Class MyJob.
using System;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
public class MyJob:SPJobDefinition
{
public MyJob() { }
//Below we can override the constructor
public MyJob(string myJobName, SPWebApplication myWebApplication) : base(myJobName, myWebApplication, null, SPJobLockType.Job) { }
//Notice the key point is to override the Execute Method and
//place our job code inside it.
public override void Execute(Guid ConetentDataBaseID)
{
SPSite mySite = new SPSite("http://mysite:port");
SPWeb myWeb = mySite.OpenWeb();
SPList myList = myWeb.Lists["{***}"];
SPListItem newitem = myList.Items.Add();
newitem["Title"] = "Insert An item Every Day"
newitem.Update();
}
}
This is just a sample job to insert to Lists["{***}"] an item every day, now we in Main entry to register this job and schedule the job using SPDailySchedule.
using System;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
static void Main(string[] args)
{
SPServer myServer = SPServer.Local;
SPSite mySite = new SPSite("http://site:port");
SPWebApplication myApplication = mySite.WebApplication;
SPJobDefinitionCollection myJobsColl = myApplication.JobDefinitions;
MyJob myJob = new MyJob("myJob", myApplication);
myJob.Title = "This is A Test Job";
SPDailySchedule myDailySchedule = new SPDailySchedule();
myDailySchedule.BeginHour = 12;
myDailySchedule.BeginMinute = 59;
myDailySchedule.BeginSecond = 0;
myDailySchedule.EndHour = 12;
myDailySchedule.EndMinute = 59;
myDailySchedule.EndSecond = 0;
myJob.Schedule = myDailySchedule;
myJobsColl.Add(myJob);
myApplication.Update();
}
In this case we build a job and register and scheduled it, it runs 12:59:00 every day.
Notice that you need to specify both the Begin and End Times. Setting the BeginHour, BeginMinute, and BeginSecond without specifying the EndHour, EndMinute, and EndSecond values will prevent the timer job from running. No error is thrown, just no execution.
You can also use FromString method of SPSchedule when let the job run at a specific time:
SPSchedule schedule = SPSchedule.FromString("daily at 12:59:00");
You can also Schedule the job every one minute, every one hour, every week, something like:
SPMinuteSchedule myMinuteSchedule = new SPMinuteSchedule();
myMinuteSchedule.BeginSecond = 0;
myMinuteSchedule.EndSecond = 59;
myMinuteSchedule.Interval = 1;
myJob.Schedule = myMinuteSchedule;
Ex 1. If we want to get all the scheduled jobs in a site:
using System;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
class Program
{
static void Main(string[] args)
{
SPSite mySite = new SPSite("http://mysite:port");
foreach (SPJobDefinition job in
mySite.WebApplication.JobDefinitions)
{
Console.WriteLine("JobName: {0} , Last Run time: {1}, Type: {2}",job .Title,job.LastRunTime.ToLongTimeString(),job.Schedule.GetType().ToString()));
}
}
}
Ex 2. If we want to delete a scheduled job.
using System;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
class Program
{
static void Main(string[] args)
{
SPSite mySite = new SPSite("http://mysite:port");
foreach (SPJobDefinition job in
mySite.WebApplication.JobDefinitions)
{
if(job.Title=="My Job")
{job.Delete();}
}
}
}
Ex 3. Now let's talk about Create a Job, and Register and Schedule it.
Create a Console Application, reference Microsoft.Sharepoint.dll, Add a new item class, call this Class MyJob.
using System;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
public class MyJob:SPJobDefinition
{
public MyJob() { }
//Below we can override the constructor
public MyJob(string myJobName, SPWebApplication myWebApplication) : base(myJobName, myWebApplication, null, SPJobLockType.Job) { }
//Notice the key point is to override the Execute Method and
//place our job code inside it.
public override void Execute(Guid ConetentDataBaseID)
{
SPSite mySite = new SPSite("http://mysite:port");
SPWeb myWeb = mySite.OpenWeb();
SPList myList = myWeb.Lists["{***}"];
SPListItem newitem = myList.Items.Add();
newitem["Title"] = "Insert An item Every Day"
newitem.Update();
}
}
This is just a sample job to insert to Lists["{***}"] an item every day, now we in Main entry to register this job and schedule the job using SPDailySchedule.
using System;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
static void Main(string[] args)
{
SPServer myServer = SPServer.Local;
SPSite mySite = new SPSite("http://site:port");
SPWebApplication myApplication = mySite.WebApplication;
SPJobDefinitionCollection myJobsColl = myApplication.JobDefinitions;
MyJob myJob = new MyJob("myJob", myApplication);
myJob.Title = "This is A Test Job";
SPDailySchedule myDailySchedule = new SPDailySchedule();
myDailySchedule.BeginHour = 12;
myDailySchedule.BeginMinute = 59;
myDailySchedule.BeginSecond = 0;
myDailySchedule.EndHour = 12;
myDailySchedule.EndMinute = 59;
myDailySchedule.EndSecond = 0;
myJob.Schedule = myDailySchedule;
myJobsColl.Add(myJob);
myApplication.Update();
}
In this case we build a job and register and scheduled it, it runs 12:59:00 every day.
Notice that you need to specify both the Begin and End Times. Setting the BeginHour, BeginMinute, and BeginSecond without specifying the EndHour, EndMinute, and EndSecond values will prevent the timer job from running. No error is thrown, just no execution.
You can also use FromString method of SPSchedule when let the job run at a specific time:
SPSchedule schedule = SPSchedule.FromString("daily at 12:59:00");
You can also Schedule the job every one minute, every one hour, every week, something like:
SPMinuteSchedule myMinuteSchedule = new SPMinuteSchedule();
myMinuteSchedule.BeginSecond = 0;
myMinuteSchedule.EndSecond = 59;
myMinuteSchedule.Interval = 1;
myJob.Schedule = myMinuteSchedule;
Subscribe to:
Posts (Atom)