| Sean's profileThe 7th (Sean Dai's Proj...BlogListsSkyDrive | Help |
|
|
November 21 Access Active Directory From SharePoint 2007 Web PartDirectoryEntry, and DirectorySearch class in System.DirectoryService namespace can be used to access and search Windows Active Directory. When you create DirectoryEntry without any credential, the system will use your default credential to access Active Directory. In ASP.NET web application, if you set impersonate=true, the application will use your login to access Active Directory.
However, in SharePoint 2007 web part, this does not work. You have to explicitly specify the username and password. Therefore, in SharePoint 2007 web part, you have to use service account to access Active Directory.
December 07 Generate .NET Code by using OlymarsOlymars, full name as SQL Server Centric .NET Code Generator, is a beta software by Microsoft, which can generate .NET code based on SQL Server database. By default, it has five build-in templates. However, developers can easily extend it to fit your needs. Here is a example to extend the templates, which can generate data access layer for application by using Microsoft Application Blocks.
To extend the templates:
1. Add a new groups in repository
2. Add a reference to System.dll in repository
3. Add a dynamic variable as CompanyName
4. Add reference of System.dll, System.Window.Forms.dll to your new group
5. Add dynamic variables as CompanyName and DeveloperAlias to your new group
6. Add three elements to your new group.
7. Edit the templates.
[Code of Templates] <*
// ----------------------------------------------------------------------------------------------------
// GetName function for element: 'Data Access Layer Interface'
// ----------------------------------------------------------------------------------------------------
public string IDataAccessLayer_GetName() {
// Choose whatever name you wish for this object
return (@"IDataAccessLayer.cs");
}
// ----------------------------------------------------------------------------------------------------
// Creation method for element: 'Data Access Layer Interface'
// ----------------------------------------------------------------------------------------------------
public void IDataAccessLayer() {
try {
Source.CurrentTemplate.ExecutionStatusMessage = "Code Generation succeed. ";
Response.WriteLine("// File Name: " + IDataAccessLayer_GetName());
Response.WriteLine("// Code Generated By: " + DynamicParameters.DeveloperAlias);
Response.WriteLine("// Code Generated On: " + System.DateTime.Now.ToShortDateString());
Response.WriteLine();
Response.WriteLine("using System;");
Response.WriteLine("using System.Data;");
Response.WriteLine();
Response.WriteLine("namespace " + DynamicParameters.CompanyName + ".Data");
Response.WriteLine("{");
Response.WriteLine("\tpublic interface IDataAccessLayer");
Response.WriteLine("\t{");
Response.WriteLine("\t\tstring ConnectionString {get;}");
Response.WriteLine("\t\tbool WithTransaction {get;}");
StoredProcedureCollection Procedures = Source.SelectedStoredProcedures;
foreach (StoredProcedure SP in Procedures)
{
string ReturnType;
if (SP.ReturnsData == true)
{
if (SP.Resultsets.Count > 1)
ReturnType = "DataSet";
else
ReturnType = "DataTable";
}
else
{
ReturnType = "void";
}
ParameterCollection Parameters = SP.Parameters;
string ParameterString = "";
foreach (Parameter P in Parameters)
{
string Direction = "";
if (P.Direction == ParameterDirection.Output)
{
Direction = "out ";
}
else if (P.Direction == ParameterDirection.ReturnValue)
{
continue;
}
if (ParameterString != "")
{
ParameterString += ",";
}
string DotNetName = P.Name;
if (DotNetName.Substring(0,1) == "@")
{
DotNetName = DotNetName.Remove(0,1);
}
ParameterString += Direction + P.DotNetType.CommonTypeSystemEquivalent + " " + DotNetName;
}
Response.WriteLine("\t\t" + ReturnType + " " + SP.Name.Replace(" ", "_") + "(" + ParameterString + ");");
}
Response.WriteLine("\t}");
Response.WriteLine("}");
}
catch (System.Exception GlobalException) {
Source.CurrentTemplate.ExecutionStatusCode = GenerationStatus.Error;
Source.CurrentTemplate.ExecutionStatusMessage = GlobalException.Message;
Response.WriteLine();
Response.WriteLine("*************************");
Response.WriteLine(" AN EXCEPTION WAS THROWN");
Response.WriteLine("*************************");
Response.WriteLine(GlobalException.Message);
Response.WriteLine();
Response.WriteLine("****************");
Response.WriteLine(" FULL EXCEPTION");
Response.WriteLine("****************");
Response.WriteLine(GlobalException.ToString());
if (Source.DesignMode) {
System.Windows.Forms.MessageBox.Show(GlobalException.ToString(), "An error has occured", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
}
else {
throw;
}
}
}
// ----------------------------------------------------------------------------------------------------
// GetName function for element: 'Data Access Layer Basic Implementation'
// ----------------------------------------------------------------------------------------------------
public string DataAccessLayer_GetName() {
// Choose whatever name you wish for this object
return (@"DataAccessLayer.cs");
}
// ----------------------------------------------------------------------------------------------------
// Creation method for element: 'Data Access Layer Basic Implementation'
// ----------------------------------------------------------------------------------------------------
public void DataAccessLayer() {
try {
Source.CurrentTemplate.ExecutionStatusMessage = "Code Generation succeed. ";
Response.WriteLine("// File Name: " + DataAccessLayer_GetName());
Response.WriteLine("// Code Generated By: " + DynamicParameters.DeveloperAlias);
Response.WriteLine("// Code Generated On: " + System.DateTime.Now.ToShortDateString());
Response.WriteLine();
Response.WriteLine("using System;");
Response.WriteLine("using System.Data;");
Response.WriteLine("using System.Data.SqlClient;");
Response.WriteLine("using Microsoft.ApplicationBlocks.Data;");
Response.WriteLine("using " + DynamicParameters.CompanyName + ".Configure;");
Response.WriteLine();
Response.WriteLine("namespace " + DynamicParameters.CompanyName + ".Data");
Response.WriteLine("{");
Response.WriteLine("\tpublic class DataAccessLayer : IDataAccessLayer");
Response.WriteLine("\t{");
Response.WriteLine("\t\t// connection string of SQL database");
Response.WriteLine("\t\tprivate string _ConnectionString = \"\";");
Response.WriteLine("\t\t// transaction option");
Response.WriteLine("\t\tprivate bool _WithTransaction = false;");
Response.WriteLine("\t\t// connection");
Response.WriteLine("\t\tprivate SqlConnection _Connection = null;");
Response.WriteLine("\t\t// transaction");
Response.WriteLine("\t\tprivate SqlTransaction _Transaction = null;");
Response.WriteLine();
Response.WriteLine("\t\t// get connection string");
Response.WriteLine("\t\tpublic string ConnectionString");
Response.WriteLine("\t\t{");
Response.WriteLine("\t\t\tget {return _ConnectionString;}");
Response.WriteLine("\t\t}");
Response.WriteLine();
Response.WriteLine("\t\t// get or set transaction option");
Response.WriteLine("\t\tpublic bool WithTransaction");
Response.WriteLine("\t\t{");
Response.WriteLine("\t\t\tget {return _WithTransaction;}");
Response.WriteLine("\t\t}");
Response.WriteLine();
Response.WriteLine("\t\t// construction with connection string");
Response.WriteLine("\t\tpublic DataAccessLayer(string Connection)");
Response.WriteLine("\t\t{");
Response.WriteLine("\t\t\t_ConnectionString = Connection;");
Response.WriteLine("\t\t}");
Response.WriteLine();
Response.WriteLine("\t\t// construction with configure");
Response.WriteLine("\t\tpublic DataAccessLayer(IConfigure Config)");
Response.WriteLine("\t\t{");
Response.WriteLine("\t\t\t_ConnectionString = Config.GetConnectionString();");
Response.WriteLine("\t\t}");
Response.WriteLine();
Response.WriteLine("\t\t// construction with connection, caller will manage the connection");
Response.WriteLine("\t\tpublic DataAccessLayer(SqlConnection Connection)");
Response.WriteLine("\t\t{");
Response.WriteLine("\t\t\tif (Connection == null)");
Response.WriteLine("\t\t\t\tthrow new Exception(\"Connection cannot be null.\");");
Response.WriteLine("\t\t\t_Connection = Connection;");
Response.WriteLine("\t\t}");
Response.WriteLine();
Response.WriteLine("\t\t// construction with transaction, caller will manage the connection and transaction");
Response.WriteLine("\t\tpublic DataAccessLayer(SqlTransaction Transaction)");
Response.WriteLine("\t\t{");
Response.WriteLine("\t\t\tif (Transaction == null)");
Response.WriteLine("\t\t\t\tthrow new Exception(\"Transaction cannot be null.\");");
Response.WriteLine("\t\t\t_Connection = Transaction.Connection;");
Response.WriteLine("\t\t\t_ConnectionString = _Connection.ConnectionString;");
Response.WriteLine("\t\t\t_Transaction = Transaction;");
Response.WriteLine("\t\t\t_WithTransaction = true;");
Response.WriteLine("\t\t}");
Response.WriteLine();
StoredProcedureCollection Procedures = Source.SelectedStoredProcedures;
foreach (StoredProcedure SP in Procedures)
{
string ReturnType;
if (SP.ReturnsData == true)
{
if (SP.Resultsets.Count > 1)
ReturnType = "DataSet";
else
ReturnType = "DataTable";
}
else
{
ReturnType = "void";
}
ParameterCollection Parameters = SP.Parameters;
string ParameterString = "";
string SqlDBParameterString = "";
int TrueParameter = 0;
foreach (Parameter P in Parameters)
{
string Direction = "";
if (P.Direction == ParameterDirection.Output)
{
Direction = "out ";
}
else if (P.Direction == ParameterDirection.ReturnValue)
{
continue;
}
if (ParameterString != "")
{
ParameterString += ",";
SqlDBParameterString += ",";
}
string DotNetName = P.Name;
if (DotNetName.Substring(0,1) == "@")
{
DotNetName = DotNetName.Remove(0,1);
}
ParameterString += Direction + P.DotNetType.CommonTypeSystemEquivalent + " " + DotNetName;
SqlDBParameterString += P.Name + " " + P.SqlFullType;
TrueParameter ++;
}
Response.WriteLine("\t\t// Execute stored procedure:");
Response.WriteLine("\t\t// " + SP.Name + "(" + SqlDBParameterString + ")");
Response.WriteLine("\t\tpublic " + ReturnType + " " + SP.Name.Replace(" ", "_") + "(" + ParameterString + ")");
Response.WriteLine("\t\t{");
if (SP.ReturnsData == true)
Response.WriteLine("\t\t\tDataSet ds = null;");
Response.WriteLine();
Response.WriteLine("\t\t\ttry");
Response.WriteLine("\t\t\t{");
if (TrueParameter > 0)
{
Response.WriteLine("\t\t\t\tSqlParameter[] Params = new SqlParameter[" + TrueParameter + "];");
Response.WriteLine();
int i = 0;
foreach (Parameter P in Parameters)
{
if (P.Direction == ParameterDirection.ReturnValue)
{
continue;
}
string DotNetName = P.Name;
if (DotNetName.Substring(0,1) == "@")
{
DotNetName = DotNetName.Remove(0,1);
}
Response.WriteLine("\t\t\t\tParams[" + i + "] = new SqlParameter(\"" + P.Name+ "\", "+ P.DotNetType.FullSqlDbTypeEquivalent + ", " + P.Length+ ");");
Response.WriteLine("\t\t\t\tParams[" + i + "].Value = " + DotNetName +";");
if (P.Direction == ParameterDirection.Output)
Response.WriteLine("\t\t\t\tParams[" + i + "].Direction = ParameterDirection.Output;");
Response.WriteLine();
i++;
}
}
string MethodName = "";
string ReturnDataSet = "";
if (SP.ReturnsData == true)
{
MethodName = "ExecuteDataset";
ReturnDataSet = "ds = ";
}
else
{
MethodName = "ExecuteNoQuery";
}
string ParamString = "";
if (TrueParameter > 0)
{
ParamString = ", Params";
}
Response.WriteLine("\t\t\t\tif (_Transaction != null)");
Response.WriteLine("\t\t\t\t{");
Response.WriteLine("\t\t\t\t\t" + ReturnDataSet+ "SqlHelper." + MethodName + "(_Transaction, CommandType.StoredProcedure, \"" + SP.Name + "\"" + ParamString + ");");
Response.WriteLine("\t\t\t\t}");
Response.WriteLine("\t\t\t\telse if (_Connection != null)");
Response.WriteLine("\t\t\t\t{");
Response.WriteLine("\t\t\t\t\t" + ReturnDataSet+ "SqlHelper." + MethodName + "(_Connection, CommandType.StoredProcedure, \"" + SP.Name + "\"" + ParamString + ");");
Response.WriteLine("\t\t\t\t}");
Response.WriteLine("\t\t\t\telse");
Response.WriteLine("\t\t\t\t{");
Response.WriteLine("\t\t\t\t\t" + ReturnDataSet+ "SqlHelper." + MethodName + "(_ConnectionString, CommandType.StoredProcedure, \"" + SP.Name + "\"" + ParamString + ");");
Response.WriteLine("\t\t\t\t}");
if (SP.ReturnsData == true)
{
if (SP.Resultsets.Count > 1)
Response.WriteLine("\t\t\t\treturn ds;");
else
Response.WriteLine("\t\t\t\treturn ds.Tables[0];");
}
else
Response.WriteLine("\t\t\t\treturn;");
Response.WriteLine("\t\t\t}");
Response.WriteLine("\t\t\tcatch(Exception ex)");
Response.WriteLine("\t\t\t{");
Response.WriteLine("\t\t\t\tthrow new Exception(\"Cannot execute the stored procedure.\", ex);");
Response.WriteLine("\t\t\t}");
Response.WriteLine("\t\t}");
Response.WriteLine();
}
Response.WriteLine("\t}");
Response.WriteLine("}");
}
catch (System.Exception GlobalException) {
Source.CurrentTemplate.ExecutionStatusCode = GenerationStatus.Error;
Source.CurrentTemplate.ExecutionStatusMessage = GlobalException.Message;
Response.WriteLine();
Response.WriteLine("*************************");
Response.WriteLine(" AN EXCEPTION WAS THROWN");
Response.WriteLine("*************************");
Response.WriteLine(GlobalException.Message);
Response.WriteLine();
Response.WriteLine("****************");
Response.WriteLine(" FULL EXCEPTION");
Response.WriteLine("****************");
Response.WriteLine(GlobalException.ToString());
if (Source.DesignMode) {
System.Windows.Forms.MessageBox.Show(GlobalException.ToString(), "An error has occured", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
}
else {
throw;
}
}
}
// ----------------------------------------------------------------------------------------------------
// GetName function for element: 'Configuration Interface'
// ----------------------------------------------------------------------------------------------------
public string IConfigure_GetName() {
// Choose whatever name you wish for this object
return (@"IConfigure.cs");
}
// ----------------------------------------------------------------------------------------------------
// Creation method for element: 'Configuration Interface'
// ----------------------------------------------------------------------------------------------------
public void IConfigure() {
try {
Source.CurrentTemplate.ExecutionStatusMessage = "Code Generated Succeed.";
Response.WriteLine("// File Name: " + IConfigure_GetName());
Response.WriteLine("// Code Generated By: " + DynamicParameters.DeveloperAlias);
Response.WriteLine("// Code Generated On: " + System.DateTime.Now.ToShortDateString());
Response.WriteLine();
Response.WriteLine("using System;");
Response.WriteLine();
Response.WriteLine("namespace " + DynamicParameters.CompanyName + ".Configure");
Response.WriteLine("{");
Response.WriteLine("\tpublic interface IConfigure");
Response.WriteLine("\t{");
Response.WriteLine("\t\tstring GetConnectionString();");
Response.WriteLine("\t}");
Response.WriteLine("}");
}
catch (System.Exception GlobalException) {
Source.CurrentTemplate.ExecutionStatusCode = GenerationStatus.Error;
Source.CurrentTemplate.ExecutionStatusMessage = GlobalException.Message;
Response.WriteLine();
Response.WriteLine("*************************");
Response.WriteLine(" AN EXCEPTION WAS THROWN");
Response.WriteLine("*************************");
Response.WriteLine(GlobalException.Message);
Response.WriteLine();
Response.WriteLine("****************");
Response.WriteLine(" FULL EXCEPTION");
Response.WriteLine("****************");
Response.WriteLine(GlobalException.ToString());
if (Source.DesignMode) {
System.Windows.Forms.MessageBox.Show(GlobalException.ToString(), "An error has occured", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
}
else {
throw;
}
}
}
*>
November 16 What's up with BeginInvoke? by S. Senthil KumarIntroductionYou are developing this shiny new multithreaded .NET application that has this spanking new UI. You are done coding and it's time for giving a demo to your boss. And while running the demo, the UI hangs. Just hangs. Damn it, you say, it was working fine on my PC. You go back to your source and try to figure out why that happened. After a lot of poking around/debugging/swearing, you notice that you call this simple property on a control and it never returns. Or sometimes, it returns, but doesn't update the UI correctly. You then read something about calling BeginInvoke. What's that, you wonder. This article will try to answer that. Note that this article will be dealing with the BeginInvoke method on the System.Windows.Forms.Control and not the BeginInvoke method that can be called on delegates to run them asynchronously. What does BeginInvoke do?According to MSDN, Control.BeginInvoke "Executes the specified delegate asynchronously on the thread that the control's underlying handle was created on". It basically takes a delegate and runs it on the thread that created the control on which you called BeginInvoke. Why do I need to do that, you ask. To understand why, you have to know about how Windows processes UI actions. Message queue and Message pumpingEvery Windows application you create is provided with a thread on startup. It's this thread that calls the Main method of your application. For a console application, you can write Main to accept user input and process them. For a GUI application, things are radically different. GUI applications are event based, which means that there needs to be some entity to process and fire events. Windows manages this by creating a message queue for your application. All UI related actions get translated to messages that get posted to this message queue 1. Now, you need someone to read the messages from the queue and call appropriate event handlers. That's what a message pump is for. It basically is a loop that waits for someone to post a message to the queue. Once someone does, it dequeues it and calls the associated event handler. It can be thought of as: Message message = null;
while ((message = GetNextMessage()) != null)
{
ProcessMessage(message);
}
}
Where does the message pump run? On the public static void Main(string[] args)
{
Form f = new Form();
Application.Run(f);
}
That fits in nicely with our theory, Application.Run will run the message loop on the thread on which it is called. In our case, it is the main thread and you can verify that the thread doesn't get past The One RuleOne of the cardinal rules of Windows GUI programming is that only the thread that created a control can access and/or modify its contents (except for a few documented exceptions). Try doing it from any other thread and you'll get unpredictable behavior ranging from deadlock, to exceptions to a half updated UI. The right way then to update a control from another thread is to post an appropriate message to the application message queue. When the message pump gets around to executing that message, the control will get updated, on the same thread that created it (remember, the message pump runs on the main thread). Let's go deeper into the Win32 world. There are two fundamental Win32 API calls to access and/or modify a control, Now it should be fairly obvious as to why the rule is around. The first reason is the blocking nature of In .NET, property/method calls on a The second reason is more subtle. Because there are effectively two queues, it's quite possible that at one point in time, both queues have the same message but with different parameters. Let's assume the message sets the text of a control and that you've used If instead of There is one other issue with using void ButtonClick_Handler(object sender, EventArgs e)
{
int val = count; // count is a class member variable
SendMessage(...);
Console.WriteLine(val == count); // Surprise, val != count can happen!
}
void SomeOtherMessageHandler()
{
count++;
}
When the above piece of code is blocking on the If you're still not convinced that Why and when to call BeginInvokeWith all that stuff inside our head now, we can easily figure out the reason for the existence of
A typical piece of code using public class FormFoo : Form
{
Label label = new Label();
public static void Main()
{
Application.Run(new FormFoo());
}
public FormFoo()
{
InitializeComponent();
Thread t = new Thread(new ThreadStart(ChangeLabel));
t.Start();
}
private void ChangeLabel()
{
for (int i = 0; i<100; ++i)
{
SetLabelText(i);
Thread.Sleep(1000);
}
}
private delegate void SetLabelTextDelegate(int number);
private void SetLabelText(int number)
{
// label.Text = number.ToString();
// Do NOT do this, as we are on a different thread.
// Check if we need to call BeginInvoke.
if (this.InvokeRequired)
{
// Pass the same function to BeginInvoke,
// but the call would come on the correct
// thread and InvokeRequired will be false.
this.BeginInvoke(new SetLabelTextDelegate(SetLabelText),
new object[] {number});
return;
}
label.Text = number.ToString();
}
}
Assigning a value to The BCL provides a Both
|
|
|