|
Didn't I tell you before that you shouldn't use string concatenation for SQL queries? What in the hell do you think the OleDbParameter and SqlParameter are for? ADO.NET introduces parameterized expressions which take ALL of the encoding work out of your application. Got a quote in one of your variables? With your way, you have to parse your values and make sure they quotes are escaped or encoded. With parameterized queries, you don't have to worry about it. Besides, massive string concatenation like you're doing is a drastic performance decrease, resulting in (m-1)O(2n) times where m is the number of strings and n is the characters in each string.
See the OleDbParameter[^] class documentation in the .NET Framework SDK for more information and an example. Most likely, not escaping or encoding your string values is what's causing that error since the string is generated and sent to the database engine AS IS.
Also, don't prompt the user before executing the query! First of all, it's annoying. Second of all, if you open the connection before prompting and they don't respond for a while (why would they think they need to answer such a stupid dialog - no other program does it; they just work). The connection gets closed and your call to ExecuteNonQuery throws an exception. Also, put your connection.Close in the finally block to make sure it gets closed on success or failure (exception). Microsoft has recommended this time and time again if you actually read the .NET Framework SDK. The finally block will always run regardless of whether or not an exception was thrown (always except for when Environment.Exit is called, which unloads the CLR - and your application - immediately).
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Hi,
I've created a custom control that inherits from ListBox, it has custom draw enabled so i can make it look almost exactly like the Outlook 2003 Inbox Listbox.
Currently i add my "Objects" to the list using the standard "Add" function in the "ListBox.ObjectCollection", however this forces me to do a type check when drawing as anything can still be added to the collection.
Ideally i would like to override the "Add" function described above to force only my "Objects" to be added, but i can't find any documentation on how to go about this.
Any example or pointer would be great to finish my control off.
Thanks in advance
|
|
|
|
|
You have to hide that member by using the new operator, which only makes it valid when the variable type is your custom ListBox derivative class:
public class MyListBox : ListBox
{
private MyListBox.MyObjectCollection items;
public new MyListBox.MyObjectCollection Items
{
if (items == null)
items = new MyListBox.MyObjectCollection();
return items;
}
private class MyObjectCollection : CollectionBase
{
}
}
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Hi.
I just found the wonderfull SuspendLayout Method on the WinForm class.
I was wondering if there is a similar feature to susoend the layout for the whole Application in multible forms, without doing it on every single form?
Something like Application.SuspendLayout();;)
Any ideas or suggestions?
|
|
|
|
|
No, and why would there be? The whole idea of object-oriented programming is that objects are responsible for themselves (encapsulation, data hiding, etc.). Each form initializes it's surface so you just need to suspend and resume the layout in each. An Application in Windows Forms really just represents the message pump that keeps the main window (Form ) alive and dispatches window messages to their respective windows.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
I have a Form containing a Panel that contains buttons.
The size of the panel will sometimes change, and I whant the bounds of the buttons to change acordenly to the panel.
Is there a method for this, or must I recalculate the bounds of all the buttons each time?
(Maybe something like setting the panel as the buttons parent)
Thanks
Thomas
|
|
|
|
|
The controls can automatically be resized, but they can't move in relation to an adjacent control's size automatically. For information on what is possible, see the Control.Anchor and Control.Dock property documentation in the .NET Framework SDK. These are exposed in the Visual Studio .NET designer as well.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Heath:
This is the second time someone asks a question like this. Simply point them to the code I posted (see post below this one).
This is a typical question from programmers that used a third party VB control, and that I believe is not available for .NET.
FYI: I know that the code posted does not work nicely with text boxes (for which I have a private solution), but it should give them a starting point to work from.
|
|
|
|
|
Second? Yeah right - try 200th. Instead of harping on me though, why don't you harp on the original posters for not searching previous forum threads BEFORE posting their (most-likely) previously-asked questions?
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Heath:
Not harping on you, nor the original poster. Repetition is the unfortunte by-product of support, which you seem to do more than your share on this board.
|
|
|
|
|
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
namespace Workbench
{
/// <summary>
/// A panel that resizes controls automatically.
/// </summary>
public class AutoSizePanel : Panel
{
/// <summary>
/// Holds the control info.
/// </summary>
private Hashtable htInfo = new Hashtable();
/// <summary>
/// Flag to prevent recursive call.
/// </summary>
private bool bAllowResize = true;
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
/// <summary>
/// Constructor.
/// </summary>
public AutoSizePanel()
{
InitializeComponent();
}
/// <summary>
/// Adds a control to the list of controls.
/// </summary>
/// <param name="e"></param>
protected override void OnControlAdded(ControlEventArgs e)
{
// Hold the resizing
bAllowResize = false;
// Create the original info
SizingInfo riData = new SizingInfo(e.Control);
// Add to table
htInfo.Add(e.Control, riData);
// BAck to normal
bAllowResize = true;
//
base.OnControlAdded (e);
}
/// <summary>
/// Removes a control from the list of controls.
/// </summary>
/// <param name="e"></param>
protected override void OnControlRemoved(ControlEventArgs e)
{
// Delete the info
htInfo.Remove(e.Control);
//
base.OnControlRemoved (e);
}
/// <summary>
/// Does the magic.
/// </summary>
/// <param name="e"></param>
protected override void OnResize(EventArgs e)
{
// Only once
if (bAllowResize)
{
// Set
bAllowResize = false;
// And apply to each control
foreach (Control ctl in this.Controls)
{
// Get the original info
SizingInfo riCtl = htInfo[ctl] as SizingInfo;
// Info available?
if (riCtl != null)
{
// Resize
riCtl.Resize(ctl);
}
}
// Reset
bAllowResize = true;
}
//
base.OnResize (e);
}
protected override void OnPaint(PaintEventArgs e)
{
// Hold the resizing
bAllowResize = false;
// Collect info
foreach (Control ctl in this.Controls)
{
// Get the original info
SizingInfo riCtl = htInfo[ctl] as SizingInfo;
// Info available?
if (riCtl != null)
{
// Update
riCtl.Update(ctl);
}
}
// Back to normal
bAllowResize = true;
//
base.OnPaint (e);
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
//
// AutoSizePanel
//
this.Name = "AutoSizePanel";
this.Size = new System.Drawing.Size(232, 184);
}
#endregion
/// <summary>
/// This holds the original control information.
/// </summary>
private class SizingInfo
{
/// <summary>
/// Info to be kept.
/// </summary>
public int iTop;
public int iLeft;
public int iHeight;
public int iWidth;
public int iParentHeight;
public int iParentWidth;
/// <summary>
/// Constructor
/// </summary>
/// <param name="ctl"></param>
public SizingInfo(Control ctl)
{
// Save
this.Initialize(ctl);
}
/// <summary>
/// Updates the internal info
/// </summary>
/// <param name="ctl"></param>
public void Update(Control ctl)
{
// Compute the change.
double dRatioHeight = (double) ctl.Parent.Height / iParentHeight;
double dRatioWidth = (double) ctl.Parent.Width / iParentWidth;
// And where it would go.
int iWTop = (int) (iTop * dRatioHeight);
int iWHeight = (int) (iHeight * dRatioHeight);
int iWLeft = (int) (iLeft * dRatioWidth);
int iWWidth = (int) (iWidth * dRatioWidth);
// Changes?
if ((iWTop != ctl.Top) || (iWLeft != ctl.Left) || (iWHeight != ctl.Height) || (iWWidth != ctl.Width))
{
// Reset
this.Initialize(ctl);
}
}
/// <summary>
/// Does the magic
/// </summary>
/// <param name="ctl"></param>
public void Resize(Control ctl)
{
// Compute the change.
double dRatioHeight = (double) ctl.Parent.Height / iParentHeight;
double dRatioWidth = (double) ctl.Parent.Width / iParentWidth;
// And shake it
ctl.Top = (int) (iTop * dRatioHeight);
ctl.Height = (int) (iHeight * dRatioHeight);
ctl.Left = (int) (iLeft * dRatioWidth);
ctl.Width = (int) (iWidth * dRatioWidth);
}
/// <summary>
/// Saves the base info
/// </summary>
/// <param name="ctl"></param>
private void Initialize(Control ctl)
{
// Save
iTop = ctl.Top;
iLeft = ctl.Left;
iHeight = ctl.Height;
iWidth = ctl.Width;
iParentHeight = ctl.Parent.Height;
iParentWidth = ctl.Parent.Width;
}
}
}
}
|
|
|
|
|
I used the "Abort()" method of class Thread in a program to cancel a thread. It seemed to function correctly, but after the main program exited, the process can still be found in processes tab of "Windows Task Manager". Whenever this line is not executed, the problem does not occur.
Is it inappropriate to cancel a thread in this manner?
|
|
|
|
|
1) Do you catch the ThreadAbortException in a loop like that?
try{<br />
for(...){<br />
try{<br />
<br />
}catch{ ... }<br />
}<br />
}catch(ThreadAbortException){ ... }
Then the thread can run for hours without doing anything.
2) You can stop the thread a clean way. Declare a boolean variable, and check it's value in the thread method:
bool threadStopped = false;<br />
...<br />
private void myThreadMethod(){<br />
doSomething();<br />
if(stopped){ return; }<br />
doSomethingElse();<br />
if(stopped){ return; }<br />
doAnything();<br />
if(stopped){ return; }<br />
...<br />
}
With that stop-variable you don't need Thread.Abort() and the try/catch stuff, because the thread stops when you set threadStopped = true .
|
|
|
|
|
I did not catch the ThreadAbortException in a loop and the execution of the tread is actually stoped.
There's still one problem with your codes: what if I want the tread to stop immediately when it is "doing something"?
|
|
|
|
|
Which is better code?
public object GetValue(Hashtable hashtable, object key)
{
if(hashTable == null)throw new ArgumentNullExeption("hashTable");
return hashtable[key];
}
or
public object GetValue(Hashtable hashtable, object key)
{
return hashtable[key];
}
Clearly the second example will throw anyway if the passed hashtable is null.
The first is more explicit if less concise. Is there any difference otherwise?
Any feedback would be appreciated.
Robert Zurer
|
|
|
|
|
For my opinion, the first is getter, you will get a cleaner error message. You should test key also.
If you have fear of the perf hit of such test you can use Debug.Assert from System.Diagnostics
Jonathan de Halleux.
www.dotnetwiki.org
|
|
|
|
|
Thank you for your response, (and also for your fine articles).
As to using Debug.Assert, I want the exception to be thrown.
(As to testing key, I may want to return null and let the caller handle that, but this is just a test example anyway.)
Am I right in assuming that the performance hit you are referring to is not the statement
if([ErrorCondition])
but the actual exception which will be thrown?
In that case, the exception would be thrown only once in either case, resulting in equal perfomance hits. Or have I missed something?
Thanks again.
Robert Zurer
|
|
|
|
|
bzurer wrote:
In that case, the exception would be thrown only once in either case, resulting in equal perfomance hits. Or have I missed something?
Totally right, anyway, to my opinion, it is always worth the price to check parameters: write such tests and documented it.
Jonathan de Halleux.
www.dotnetwiki.org
|
|
|
|
|
Thanks for you response, (and also for your fine articles).
I want to throw the exception so Debug.Assert wouldn't work here.
I assume that the perfomance hit you are talking about is the actual exception and not the if statement. If I haven't misunderstood, wouldn't one exception be thrown in either case resulting in equal performance hits?
Robert Zurer
|
|
|
|
|
IMO, throw the ArgumentNullException . If you don't, the CLR will throw a NullReferenceException , and those are always annoying because any reference Type throughout the executing code could be null and you'll have to debug to find out which. Throwing the ArgumentNullException exception should make it obvious. Either way, the calling code should catch the exception and display a user-friendly error (though in this example, there's no excuse for an exception being thrown in a release app).
In the base class library assemblies, any params that shouldn't be null are checked in this manner.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Is it possible to have a propety as an array? If so, how do I access it??
I usually create my properties in this manner
class Object{
private string sProperty;
public string Property{
get{return sProperty;}
set{sProperty = value;}
}
Can I do the following, and how do I properly access the array
class Object{
private string[] sProperty;
public string[] Property{
get{return sProperty;}
set{sProperty = value;}
}
|
|
|
|
|
I don't know about string[], but if you use ArrayList like:
private ArrayList alBtnCommands = new ArrayList();
public ArrayList ButtonCommands
{
get
{
return alBtnCommands;
}
set
{
alBtnCommands = value;
}
}
then you can call it by:
currentButton.ButtonCommands.Add(AnItem);
currentButton.ButtonCommands.RemoveAt(i); // i(integer) is an index
SomeThing = currentButton.ButtonCommands[i];
currentButton.ButtonCommands[i] = SomeThing;
It's not what you asked for, but it might be similar for string[]
Hope it helps
Thomas
|
|
|
|
|
Using an IList implementation like the ArrayList isn't always the answer. An array is fixed. Items can't be added or removed. This is often necessary in cases like returning the fonts installed on the system, or returning the printers installed on the system. In these cases, though, the property is read only (only implements the get accessor). If it was a list, developers can easily modify it (without even instantiating a new one) which might corrupt the behavior of the object.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Do it just like you wrote :
<br />
public string[] Property{ <br />
get{return sProperty;}<br />
set{sProperty = value;}<br />
}<br />
and access it like so
<br />
Object o = new Object();<br />
o.Property = new String[] {"foo", "bar"};<br />
Console.WriteLine("{0} {1}", o.Property[0], o.Property[1]);<br />
another trick is to use default properties[^]
write you property like this
<br />
public string this[int index] {<br />
get { return sProperty[index]; }<br />
set { sProperty[index] = value; }<br />
}<br />
and access like this
<br />
Object o = new Object();<br />
o.Property = new String[2];<br />
o[0] = "foo";<br />
o[1] = "bar";<br />
Console.WriteLine("{0} {1}", o[0], o[1]);
HTH
The smaller the mind the greater the conceit.
Aesop
|
|
|
|
|
The cop (FxCop) says do not return array as properties...
Jonathan de Halleux.
www.dotnetwiki.org
|
|
|
|