 |
|
 |
Is it possible to use these classes with the objectdatasource? I can't seem to figure out how that would work with the datatable built into the class like that.
Rich
http://www.devanddesign.com/
|
|
|
|
 |
|
 |
Great and best tool.
Really very very usefull
|
|
|
|
 |
|
 |
A while ago, I searched the internet for a code generator of stored procedures with simple feactures:
- No further modification to the generated code
- Synchronizing with procedure changes
- Directly interacting with data provider methods
- Flexible for effecient use of ADO.Net functionality
- Static data binding
There are a lot of such kind but I had no success.
Now, I have created one and if you are interested, take a look at
http://www.povb.com/posharp
Chris Liang
|
|
|
|
 |
|
 |
... or just use one of the many free tools like MyGeneration:
www.mygenerationsoftware.com
Kind regards,
thomas
People who wait until the eleventh hour to call on Jesus die at 10:30.
|
|
|
|
 |
|
 |
First to say that your article was very very helpful, however the generated code sucks.
Just spend a couple of minutes thinking.
Take a look at the exceptions thrown. These 2 cases could be the first in the procedure:
if ((connection == null))
{
throw new System.ArgumentException("The connection object cannot be null");
}
else
{
if ((connection.State == System.Data.ConnectionState.Closed))
{
.................
}
else
{
throw new System.ArgumentException("The connection" +
" must be closed when calling this method.");
}
Instead of this you could have something way cleaner:
if ((connection == null))
{
throw new System.ArgumentException("The connection object cannot be null");
}
if ((connection.State != System.Data.ConnectionState.Closed))
{
throw new System.ArgumentException("The connection" +
" must be closed when calling this method.");
}
Spending a big more time on that it turns out that you will have this piece of IDENTICAL code for every single stored procedure in your data access layer. So you could make it a separate function and just call it. Also this should be done only duting testing and that's why you should be using ASSERT so they won't be compiled in the release.
Another bad part: Resource protection. After you open the database you should wrap the code before closing the database in a try-finally block:
connection.Open();
try
{
cmd = new System.Data.SqlClient.SqlCommand("wl_AddUser", connection);
.............
}
finally
{
connection.Close();
}
Additionally you could put the execution code in another function and just pass the "cmd".
Another part I didn't understand is why are you defining the "cmd" variables in the beginning.
Also why are you requiring a table always but not only when it is neccessary? You said it's faster to use a reader and copy the data to the passed table "manually", but couldn't you create another function to do that to avoid identical code in your program again and again?
Also thinking about what code you will be generating again and again - you could initialize the SqlCommand and pass it to another function to actually perform the stored procedure call.
Here's the result after slightly fixing your code:
private static void CheckConnection(System.Data.SqlClient.SqlConnection connection) {
if ((connection == null)) {
throw new System.ArgumentException("The connection object cannot be null");
}
if ((connection.State == System.Data.ConnectionState.Closed)) {
throw new System.ArgumentException("The connection must be closed when calling this method.");
}
}
private static void ExecuteSqlCommand(System.Data.SqlClient.SqlCommand cmd, System.Data.DataTable table) {
connection.Open();
try {
if ((table != null)) {
System.Data.SqlClient.SqlDataReader reader = cmd.ExecuteReader();
try {
if (reader != null) {
table.Clear();
table.Columns.Clear();
for (int i = 0; (i < reader.FieldCount); i = (i + 1)) {
System.Type __type;
string __name;
__type = reader.GetFieldType(i);
__name = reader.GetName(i);
table.Columns.Add(__name, __type);
}
while(reader.Read()) {
System.Data.DataRow row = table.NewRow();
object[] rowdata = new object[reader.FieldCount];
reader.GetValues(rowdata);
row.ItemArray = rowdata;
table.Rows.Add(row);
}
}
} finally {
reader.Close();
}
} else {
cmd.ExecuteNonQuery();
}
} finally {
connection.Close();
}
}
public static int wl_AddUser(System.Data.SqlClient.SqlConnection connection,
System.Data.DataTable table, string uname, string pwd,
bool IsUserAdmin, bool IsProviderAdmin, bool IsWaitlistAdmin,
bool IsUser, ref int uid) {
int RETURN_VALUE = 0;
CheckConnection(connection);
System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand("wl_AddUser", connection);
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Parameters.Add("@RETURN_VALUE", System.Data.SqlDbType.Int, 0);
cmd.Parameters["@RETURN_VALUE"].Direction = System.Data.ParameterDirection.ReturnValue;
cmd.Parameters["@RETURN_VALUE"].Value = RETURN_VALUE;
cmd.Parameters.Add("@uname", System.Data.SqlDbType.VarChar, 50);
cmd.Parameters["@uname"].Direction = System.Data.ParameterDirection.Input;
cmd.Parameters["@uname"].Value = uname;
cmd.Parameters.Add("@pwd", System.Data.SqlDbType.VarChar, 50);
cmd.Parameters["@pwd"].Direction = System.Data.ParameterDirection.Input;
cmd.Parameters["@pwd"].Value = pwd;
cmd.Parameters.Add("@IsUserAdmin", System.Data.SqlDbType.Bit, 0);
cmd.Parameters["@IsUserAdmin"].Direction = System.Data.ParameterDirection.Input;
cmd.Parameters["@IsUserAdmin"].Value = IsUserAdmin;
cmd.Parameters.Add("@IsProviderAdmin", System.Data.SqlDbType.Bit, 0);
cmd.Parameters["@IsProviderAdmin"].Direction = System.Data.ParameterDirection.Input;
cmd.Parameters["@IsProviderAdmin"].Value = IsProviderAdmin;
cmd.Parameters.Add("@IsWaitlistAdmin", System.Data.SqlDbType.Bit, 0);
cmd.Parameters["@IsWaitlistAdmin"].Direction = System.Data.ParameterDirection.Input;
cmd.Parameters["@IsWaitlistAdmin"].Value = IsWaitlistAdmin;
cmd.Parameters.Add("@IsUser", System.Data.SqlDbType.Bit, 0);
cmd.Parameters["@IsUser"].Direction = System.Data.ParameterDirection.Input;
cmd.Parameters["@IsUser"].Value = IsUser;
cmd.Parameters.Add("@uid", System.Data.SqlDbType.Int, 0);
cmd.Parameters["@uid"].Direction = System.Data.ParameterDirection.InputOutput;
cmd.Parameters["@uid"].Value = uid;
ExecuteSqlCommand(cmd);
uid = ((int)(cmd.Parameters["@uid"].Value));
RETURN_VALUE = ((int)(cmd.Parameters["@RETURN_VALUE"].Value));
return RETURN_VALUE;
}
I could keep optimizing and create a couple more functions for the parameters to clean it up as well.
I hope you will take this as constructive critics not criticising you. I borrowed a couple of ideas from your article by now and I think it's very helpful.
|
|
|
|
 |
|
 |
Hi
The Northwind database has Procedure names with Spaces Ex( Ten Most Expensive Products). How do i call those procedures from Java
I have tried the below options
{? = call Northwind.dbo.Ten Most Expensive Products}
{? = call Northwind.dbo.[Ten Most Expensive Products]}
{? = call [Northwind].[dbo].[Ten Most Expensive Products]}
{? = call [Northwind].[dbo].[Ten Most Expensive Products]()}
{? = call [Northwind].[dbo].[Ten_Most_Expensive_Products]}
Though i pass the procedure name with spaces still getting error
Exception in thread "main" java.sql.SQLException: [Microsoft][SQLServer 2000 Driver for JDBC][SQLServer]Could not find stored procedure 'Northwind.dbo.TenMostExpensiveProducts'.
Kindly let me know the right way of passing the procedure name to exectue.
Thanks
Numburisat
|
|
|
|
 |
|
 |
Have you seen http://www.mygenerationsoftware.com
MyGeneration is an extremely flexible development tool written in Microsoft .NET. MyGeneration generates code from templates that can be written in C#, VB.NET, JScript, and VBScript. MyGeneration is great at generating ORM architectures or O/R Mapping files for architectures such as Gentle.NET, NHibernate, and others. The meta-data from your database is made available to your templates through the MyMeta API. MyGeneration supports Microsoft SQL, Oracle, IBM DB2, MySQL, PostgreSQL, Microsoft Access, FireBird, Interbase, SQLite and VistaDB.
MyGeneration also ships with a very popular .NET architecture available in C# and VB.NET known as dOOdads
See http://www.mygenerationsoftware.com/dOOdads/CSharp_MasterSample.aspx[^]
|
|
|
|
 |
|
 |
Could you add or tell me where to add code to integrate Windows Integrated Security and be able to select Database. I made a simple attempt but failed?
"Server=localhost;Integrated Security=SSPI; Database=Pubs"
Regards & Thank you ,
Mark
|
|
|
|
 |
|
 |
The edit boxes should not be the same color as the background-- it should generally be white. In this color, it appears like you can't edit the fields.
It's a really great application! Thanks!
|
|
|
|
 |
|
 |
I'll add that into the next version (due out next week sometime) as well as J# support
Thanks for the comment
|
|
|
|
 |
|
 |
look who i found of this thing...father...deadbeat...=P
lookin 4 deadbeat d =P
|
|
|
|
 |
|
 |
I have a DBHelper type class for all my SProc calls, etc. as mentioned early in this article, and many of the functions return DataTables. What I'm wondering is instead of using DataAdapter.Fill and returning a DataTable, should I use a Reader and pass it to another simple function that builds a DataTable out of it and returns that? Would that be more efficient?
Also, how do you learn/know little efficiency tid-bits like this?
|
|
|
|
 |
|
 |
Wether or not you should use datatables depends on the needs of your applicaiton. For me it is a simple choice, I do not allow direct access to the database, all calls have to go through stored procedures. As such I do not need the additional overhead/flexibility that a dataadapter provides.
As for how do you learn, expierance and examining the code for both various classes involved.
HTH
|
|
|
|
 |
|
 |
I've been trying to figure out how to code a call to sp_helpdb and have get back it's values.
leppie pointed me to this article but I don't think it's a fit ... ?
Thanks,
cb
|
|
|
|
 |
|
 |
I'm not quite sure what you mean.
If you look in LocateDB.cs you will find a method _CheckValid that loads a list of databases from a specific server, however I use the sp_databases call. Using sp_helpdb is really the same kind of call, it simply returns more information than I needed.
HTH
|
|
|
|
 |
|
 |
Have u think in use DAAB
... Microsoft Data Access Application Block ?
great job !!! 5 (*) for u !!!
MCP Bruno Capuano
Jefe de Desarrollo
PECTRA Technology Inc.
All the Solutions in One Product
+54(351)4245756 - int. 301
www.pectra.com
|
|
|
|
 |
|
 |
Hi!
I was wondering if there is a special reason for the approach you used to populate the datatable?
Wouldn't it be easier to use a DataAdapter?table = new DataTable();
SqlDataAdapter da = new SqlDataAdapter(cmd); da.Fill(table);
[Added]Also; mark the table parameter as "out" in the parameter list on top.
Have a look at my latest article about Object Prevalence with Bamboo Prevalence.
|
|
|
|
 |
|
 |
The answer is simple, overhead. While it is less typing to fill a datatable by calling IDataAdapter.Fill(x) it adds nothing to the finished datatable and carries quite a bit of overhead. Since I am not typing the code, I choose to go for lower overhead, higher performace with slightly more verbose code.
Feel free to modify to suite your needs and desires
|
|
|
|
 |
|
|
 |
|
 |
This is a very useful tool. Thank you!
I can see that DataTables are created by the wrapper. As I recall, by default values are passed by value in C#. Do I have to modify the generated code to retrieve the DataTable? If so, that is not a problem.
Danny Crowell is the president and founder of Crowell Solutions, Inc. and has been developing enterprise systems since 1993. Crowell Solutions is a software company that develops custom database applications. They save organizations time and money by helping them capture, transfer, and report information. Visit them online at www.crowsol.com.
|
|
|
|
 |
|
 |
Danny Crowell wrote:
As I recall, by default values are passed by value in C#.
The "value" that is beeing copied ( = passed by value) here is the reference to the DataTable object. Both references point to the same DataTable object.
So if I hva understood you right; No, you don't have to modify the generated code to retrieve the DataTable...
Have a look at my latest article about Object Prevalence with Bamboo Prevalence.
|
|
|
|
 |
|
 |
Arjan is completely correct you don't have to modify the generated code, just pass in a valid datatable. Be aware that the current contents (if any) of the datatable will be cleared by the method before inserted the results from the stored procedure. If you don't care about the return set (or if the stored proc doesn't have any) simply pass in null for the datatable (nothing for you VBer's out there).
Regards
Charles Horan
|
|
|
|
 |
|
 |
Hi Charles,
great work, this is the way code generation tools made their start.
As you will probably see, there will be a lot of request's, how the generated code should look like, and over time , it gets very fuzzy to implement all these request, even if they are your own.
I didn't stepped through the code, but I assume, you hardcoded the output code for all languages you like to support. A more elegant way of doing this would be the use of templates, where you can make the changes how the generated code should look like without touching the application.
Please don't consider this as advertising as the tool I am now going to mention is free to use and comes with a huge free usable template library, and I am not affiliated with the developers of this tool.
mygeneration (www.mygenerationsoftware.com) is a template based code generation utility with full database meta data support for mssql, msaccess, oracle, mysql and postgre giving you all necessary schema information for generating all kind of database application code. You have access to tables, stored procedures, views, indices, primary / foreign keys, fields you can use to build your code.
There is already a quite impressive template library for building all kind of code, such as wrappers for db tables and stored procedures up to a little, charming framework (called dOOdads) for accessing data (load, create, insert, update, delete, sort, filter, ....).
The templates support either ms script (vbscript, jscript) or net scritp (c#, vb.net). The output language is up to your imagination (c#, vb.net, html, sql, ....).
The template library is growing from day to day by submitted user inputs.
If it is your intention to see how code generation could be done, then go on with your solution and improve it, lots of people will like it.
But if you don't want to reinvent the wheel and want to save valuable time, mygneration already provides all you need that you can use to develop your own templates. This way you can concentrate on improving the output code and not the tool to build it.
At least, give it a look. After switching to mygeneration, I love this tool more and more the more I use it and it saved me lots of time. And the best is, the developers are open to user feature requests, which , in some cases, are implemented in a very short time. The update cycles at the moment vary from 5 to 14 days.
Marc Sommer
mygeneration web site : www.mygenerationsoftware.com
mygeneration forums : http://www.mygenerationsoftware.com/phpbb2/
mygeneration Template Library : http://www.punktech.com/mygeneration/
|
|
|
|
 |
|
 |
Marc,
Thanks for your response, and I will agree that in it's current state the generator is primitive. In the sense that it is intended to solve a single issue in a standard method. However primitive does not equate to without use. This tool was written for my purposes for my projects, it was never meant to be a general purpose database generation tools, though the hooks are there to make it so. While the structure of the code is predefined, to use your words a template, the generation of the language specific code is left to drivers that implement the CodeDom interface. Also the code that determines the strucuture has been factored at a high level so that in the future, if I feel the need, I can go back and allow users to customize the current template to suite thier need.
Regards
Charles Horan
|
|
|
|
 |
|
 |
Note: Names of stored procedures can include blanks (like: 'Sales by Year' in the Northwind DB), which leads to wrong C# procedurenames.
|
|
|
|
 |