C# For You
[Most Recent Entries]
[Calendar View]
[Friends]
Below are the 7 most recent journal entries recorded in
Larry's C# Musings' LiveJournal:
| Sunday, February 5th, 2006 | | 10:20 pm |
Aside
Here are some musings about a couple of things I ended up doing this weekend. First, the Splitter Control that you get in Visual Studio isn't the most obvious thing in the world to start working with. But, it is insanely easy to use once you know how. Put part A, Dock A to the left. Put your Splitter and also dock it to the left. Put part B and dock it to the middle. Done. The splitter will now let you divide the space in the window between A and B. Second, the Reflection.Emit works pretty much like they say on the MSDN site http://msdn2.microsoft.com/en-us/library/system.reflection.emit.propertybuilder.aspx. I borrowed liberally from the code there and just tweaked it enough to allow you to input the object description in an XML like syntax. Some things I have yet to do include: setting the default values for the properties and attributing the properties to make them work with the PropertyGrid better http://www.c-sharpcorner.com/Code/2004/June/PropertyGridInCSharp.asp. I currently have the example reading in XMLish descriptions like:
< class name="bob" >
< property name="oneString" type="System.String" default="hi"/ >
< property name="oneInt32" type="System.Int32" default="hi"/ >
< property name="twoString" type="System.String" default="hi"/ >
< /class >
and producing an internal assembly as well as saving it out to the disk. It also uses ILDASM to disassemble the .dll and displays the results. Lastly, it instantiates one of the new objects and hooks it to a PropertyGrid. I should get this finished and integrated into the SQLTester sometime this week. Project( Image ) | | Sunday, January 29th, 2006 | | 10:34 pm |
Using SQL server from a WinForm (Part 4)
Ok, lets dig into the results we are getting and get some type information. The system table systypes has the information about the types we are retrieving. If we alter our SQL we can get this information back in the same query:
SELECT * FROM
(
SELECT
sc.colid, sc.name, sc.length, sc.xprec, sc.xscale, st.name AS typeName, st.name AS extTypeName
FROM
syscolumns sc
JOIN
sysobjects so ON so.id = sc.id
JOIN
systypes st ON st.xtype = sc.xtype and st.xusertype = sc.xusertype
WHERE
so.name = 'sp_help'
AND
sc.xtype = sc.xusertype
UNION
SELECT
sc.colid, sc.name, sc.length, sc.xprec, sc.xscale, st.name AS typeName, stExt.name AS extTypeName
FROM
syscolumns sc
JOIN
sysobjects so ON so.id = sc.id
JOIN
systypes st ON st.xtype = sc.xtype AND st.xtype = sc.xusertype
JOIN
systypes stExt ON st.xtype = sc.xtype AND st.xusertype = sc.xusertype
WHERE
so.name = 'sp_help'
AND
sc.xtype != sc.xusertype
) x
ORDER BY x.colid
There are two sub queries unioned together because you can do a derived type that is built up of native types. This way, both names are available. Now we can build up our object using Reflection.Emit and hook a PropertyGrid up to it for our UI. I found an article at Code Project that has a library for doing just this, but I didn't care for the implementation: http://www.codeproject.com/cs/miscctrl/CustomPropGrid.asp. This post is late and light on code. (*sigh*) I am going to have to come back next time and build the object with properties. I am probably going to base it on code from http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemreflectionemitpropertybuilderclasstopic.aspproject files and source code | | Sunday, January 15th, 2006 | | 10:51 pm |
Using SQL server from a WinForm (Part 3)
Continuing with the SqlServerTester, let's begin to add the ability to automatically generate a call to a selected stored procedure. - Add a new
GroupBox containing RadioButtons for the Stored Procedure Type (System or User) with appropriate background code, a ComboBox to contain the stored procedure names, and a generate Button.
- We are going to extend the
RadioButton EventHandler model to include an action other than just keeping the buttons selected correctly by adding a call to another procedure just after the setting of the currently selected RadioButton Checked to true:
private void StoredProcedureType_CheckedChanged(object sender, System.EventArgs e)
{
this.radSystem.CheckedChanged -= new System.EventHandler(this.StoredProcedureType_CheckedChanged);
this.radUser.CheckedChanged -= new System.EventHandler(this.StoredProcedureType_CheckedChanged);
radSystem.Checked = false;
radUser.Checked = false;
((RadioButton) sender).Checked = true;
UpdateStoredProcedureComboBox();
this.radSystem.CheckedChanged += new System.EventHandler(this.StoredProcedureType_CheckedChanged);
this.radUser.CheckedChanged += new System.EventHandler(this.StoredProcedureType_CheckedChanged);
}
- To fill our
ComboBox with stored procedure names, we will query the System Tables with the sql:
string sql_GetStoredProcedures = "select name from sysobjects where xtype = 'p'";
- To create our stored procedure template, we need to query another System Table, this time, the
syscolumns one. For now, let's just get the results and put them in the DataGrid with the following sql:
string sql_GetStoredProcedures = "select sc.* from syscolumns sc join sysobjects so on so.id = sc.id where so.name = '"+cmbStoredProcedures.SelectedItem+"'";
That's it for today. Next, we will look at an interesting way of using Remoting.Emit Reflection.Emit and a PropertyGrid to get values for the stored procedure parameters. project files and source code | | Monday, January 9th, 2006 | | 12:02 am |
Using SQL server from a WinForm (Part 2)
Continuing with the same solution, let's explore three different ways to connect to the same database. We used the native System.Data.SqlClient to connect last time, lets also try an ODBC and an OLE connection.
- Add
using System.Data.Odbc; and using System.Data.OleDb;
- We'll also add some RadioButtons for the connection type (
radNativeSQL, radODBC, and radOle). To keep them visually separate, add a couple of GroupBox(es) to put them in.
- Instead of using a
SqlConnection, SqlCommand, and SqlDataAdapter; we will use the interfaces IDbConnection, IDbCommand, and IDbDataAdapter. These are interfaces that it is required for data providers to implement.
IDbCommand command = null;
IDbConnection conn = null;
IDbDataAdapter dataAdapter = null;
- Within the run button click event handler (btnRun_Click) add code to open the different type connections as shown below:
conn = new SqlConnection(txtConnectionString.Text);
conn.Open();
command = new SqlCommand(txtSQL.Text, (SqlConnection) conn);
dataAdapter = new SqlDataAdapter();
conn = new OdbcConnection(txtConnectionString.Text);
conn.Open();
command = new OdbcCommand(txtSQL.Text, (OdbcConnection) conn);
dataAdapter = new OdbcDataAdapter();
conn = new OleDbConnection(txtConnectionString.Text);
conn.Open();
command = new OleDbCommand(txtSQL.Text, (OleDbConnection) conn);
dataAdapter = new OleDbDataAdapter();
- In a similar way, add the controls and code to handle the three different ComandType(s):
CommandType.StoredProcedure, CommandType.TableDirect, and CommandType.Text
- We will also add the ExecuteNonQuery Query type.
You will need to provide different connection strings depending on the connection type you want to use. Here are the ones I use at home for testing:
[native sql server]
Password=xxxx;Persist Security Info=True;User ID=Golf;Initial Catalog=Commerce;Data Source=CORNBREAD
[odbc]
Driver={SQL Server};Server=CORNBREAD;UID=Golf;PWD=xxxx;Database=Commerce;
[oledb]
Provider=SQLOLEDB.1;Password=xxxx;Persist Security Info=True;User ID=Golf;Initial Catalog=Commerce;Data Source=CORNBREAD
Play around with the different connection types and command types and notice how different combinations behave differently (for example, only Ole implements TableDirect). Also try executing sp_help 'sysobjects' with each of the connection types/command types. project files and source code | | Friday, January 6th, 2006 | | 10:34 am |
(enumType)Enum.Parse(typeof(enumType),stringOfEnum)
Quick tip on converting from a string into an enumeration. Given:
enum MyShape
{
Circle,
Triangle,
Square,
Rhombus
}
you can do:
MyShape bob;
bob = (MyShape) Enum.Parse(typeof (MyShape), "Square", true);
MyShape jim;
jim = (MyShape) Enum.Parse(typeof (MyShape), "cIRcLE", true);
| | Thursday, January 5th, 2006 | | 11:15 pm |
Using SQL server from a WinForm (Part 1)
- Start with a simple windows form.
- Add a
TextBox and a Lable for the connection string.
- Get your connection string by creating a text document on your desk top and changing the name to bob.udl. Double click on it and you get the Data Link Properties application that walks you through connecting. Then open up bob.udl (Universal Data Link?) in a text editor and bob's your uncle. Ok, you must remove the
Provider=SQLOLEDB.1; from it to make it work correctly, but it is still a cool way to get a connection string.
- Add a SQL
Lable and TextBox.
- Next, add a multiline output
TextBox and a run Button. Add an EventHandler for the Click event on the Run button by double clicking on it.
- Add a
using System.Data.SqlClient; to the top and then open your connection to the SQL database using the supplied connection string, and run the supplied command against it, putting the output into the output TextBox. At this point, we are going to ExecuteScalar and expect only a single value back.
SqlConnection conn = new SqlConnection(txtConnectionString.Text); conn.Open(); SqlCommand command = new SqlCommand(txtSQL.Text,conn); txtOutput.Text = command.ExecuteScalar().ToString();
- Let's run it and see what we get. Use the following SQL
select count(distinct name) from sysobjects where name not like '%sys%';. I get 46 as my output, because I have created 46 user defined objects in the database I am connecting to.
- Well, what if we want to get back more than a single value? Let's start by extracting a method that contains lines 3 and 4 from above. We then add a second output control, a
DataGrid. We want to get a DataSet back from SQL so that we can bind it to the control. We use a DataAdapter to fill our DataSet and then assign it as a DataSource on the DataGrid. Add the folowing code in a new method:
SqlCommand command = new SqlCommand(txtSQL.Text,conn); SqlDataAdapter sda = new SqlDataAdapter(command); DataSet dataSet = new DataSet("GetDataSet Results"); sda.Fill(dataSet); dgrOutput.DataSource = dataSet;
- We will need to add some type of control to decide which one of these methods we want to run when you press the run button. Let's use a couple of
RadioButton(s) and code to hide the TextBox or DataGrid depending on what results are returned. I always set one (and only one) RadioButton to Checked and then build a method to be fired by all of them that hides/unhides and checks/unchecks as required. You should add something like this:
this.radExecuteScalar.CheckedChanged -= new System.EventHandler(this.radioButton_CheckedChanged); this.radDataAdapter.CheckedChanged -= new System.EventHandler(this.radioButton_CheckedChanged); radExecuteScalar.Checked = false; radDataAdapter.Checked = false; ((RadioButton)sender).Checked = true; this.radDataAdapter.CheckedChanged += new System.EventHandler(this.radioButton_CheckedChanged); this.radExecuteScalar.CheckedChanged += new System.EventHandler(this.radioButton_CheckedChanged);
- Add some code to the run button event handler to choose which method to run based on the radio button checked and you are done.
- Try executing
select * from sysobjects with the new code. What happens when you try it with the old code? How about when you try and execute a stored procedure like sp_who?
project files and source code | | Tuesday, October 11th, 2005 | | 3:28 pm |
Isolated Storage Isolated storage is a managed disk access method encompasing security“Isolated storage is a data storage mechanism that provides isolation and safety by defining standardized ways of associating code with saved data.” 1 Isolated storage files are stored within the private data of the user running the application. In fact, the framework determines the location of the file system available to your program (this works sort of like a chroot padded cell in Linux land) in isolated storage depending on what IsolatedStorageScope you define when you get access to the store. A single program can open several files with the same name in many different locations by using differently scoped stores. Using isolated storage conforms to least privilege principalsWhy should you care about isolated storage? It will be much more important with the release of Vista and the greater integration of Code Access Security (CAS) 2 and User Account Protection (UAP) 3 . These two technologies allow Administrators and Users fine grained control on what resources a program has access to. Using the development practice of “Least Privilege” 4 , we should not request access to the file system to simply store user configuration information. Likewise, accessing the registry (which has been a favorite place for storing configuration information) is problematic to implement and requires privileges not granted to programs by default, thus violating least privilege again. Vista does allow elevation of rights for users who have administrative privileges but asking the user to elevate each time a setting changed wouldn’t be a very good user experience. ( Examples: )Sources: 1 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconIsolatedStorage.asp2 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconcodeaccesssecurity.asp3 http://msdn.microsoft.com/windowsvista/security/4 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncode/html/secure06112002.asp |
|