|
This is called boxing and unboxing[^]. When you pass a struct by reference or as an object (including interfaces) an object is created on the heap to match the struct and the struct's data is copied to the object. Unboxing is when an instance of a struct is created and the object data is copied to its fields. This is a very expensive operations and is one of the major reason that generics were introduced into the CLI 2.0 and C# 2.0.
Ask yourself why you have a struct? Is it a remnant of your C/C++ experience? Forget what you know about pointers in C/C++. It hardly applies (it's still important when P/Invoking and with COM interop, but you seem to already have some idea since you know about pinning).
Structs in .NET are for short-lived, small data structures. Anything that has a lifespan and gets passed around quite a bit should be a class.
If you use a disassembler like ildasm.exe or a decompiler like .NET Reflector you can actually see that instead of structs Microsoft uses classes internally within the BCL quite a bit to avoid the boxing and unboxing. When the class is marshaled to managed code - and is attributed and written to align properly - native code sees it as a struct. A class is, after all, not much different than a struct in native code.
This posting is provided "AS IS" with no warranties, and confers no rights.
Software Design Engineer
Developer Division Sustained Engineering
Microsoft
[My Articles] [My Blog]
|
|
|
|
|
The purpose of ref and out keywords is to make your code more readable and usable for other developers. (And not to convert value type to reference types, although it is a side-effect)
Each time you want to refer a value type as reference type, is it ‘boxed’ i.e. copied to heap and the reference is thus created.
To answer your final question: Ideally (since structures are value types in C#) you should have them lightweight, that ensures best performance. If your structure is big, it is an ideal candidate to be an reference type (a class object).
Salil Khedkar [^]
|
|
|
|
|
hi,
i am writing a simple Stored Procedure [Sql Server 2000] to check employee's login ... this stored procedure.. supposed to return "YES" or "NO.. if login and password match... here is the code for stored procedure :
----------------------------------
CREATE PROCEDURE spCheckEmpLogin
@Login char(6), @EmpPassword char(8) , @RetVal char(3) OUTPUT
AS
DECLARE @tmp char(4)
SELECT @tmp = EmpPassword FROM tblEmployees WHERE Login=@Login
IF @tmp <> @EmpPassword
BEGIN
@RetVal = 'NO'
END
RETURN;
GO
---------------------------------------
when i click on "Check Syntax" button.... server returns this error :
Error 170: Line 11 : Incorrect Syntax near '@RetVal'
......................................................
well ... in line 11 : i am assigning 'No' to @RetVal... [it's a simple assignment]....
can you please tell me what i am doing wrong????
thanx in advance
|
|
|
|
|
Hi,
First of all, I think you posted this message in the wrong message board (this is C#).
In answer to your question, line 11 should read like this:
SET @RetVal = 'NO'
Hope this helps!
~javier lozano
(blog)
|
|
|
|
|
hello,
i have the table brands with 2 columns brand_id and name. I'm creating a new row in my dataset in the table brands after i added the new row i need to update the database that is no problem but the auto increment number that is created for example brand_id: 11
i need that number. The database where the data is stored in is a firebird database.
DataRow drBrand = dS.Tables["brands"].NewRow();
drBrand["name"] = "new brand";
dS.Tables["brands"].Rows.Add(drBrand);
adapterBrands.InsertCommand.Transaction = connection.BeginTransaction();
adapterBrands.Update(dS.GetChanges(), "brands");
adapterBrands.InsertCommand.Transaction.Commit();
So what i want is: I create a new row in the table brands with the name: "new brand" the database creates automatically a new auto increment number for example: 11 but the dataset is not updated when i view the dataset the value of: drBrand["brand_id"] = 0 it says. Can somebody help me to get the right auto increment number in the dataset so i can use that auto increment number.
thx
Sander
|
|
|
|
|
The way NET normaly does it (at least in SqlDataBases) is appending a Select command to the insert command in order to refresh the data in your dataset. I'm not really sure what parameters are used, but just create a small example with a SqlDataAdapter via designer and check out the insert commandtext. U'll see what I mean inmediately.
|
|
|
|
|
As I already told you, you need to read the documentation. connection.BeginTransaction will not update your your changes. DataAdapter.Update will connect to the database using the connection string, update the changes, then disconnect. A transaction only works when you're connected, and Update encapsulates that.
And as I also said before that the other post mentioned, you need to combine your INSERT statement with a SELECT statement and NOT insert your auto-generated fields, like so:
SqlCommand insertCommand = connection.CreateCommand();
insertCommand.CommandText = "insert into brands (name) values (@name); select id, name from brands";
insertCommand.Parameters.Add("@name", SqlDbType.NVarChar, 40).Value = "Bob";
adapterBrands.Update(ds.GetChanges(), "brands"); You may also need to set up the TableMappings property to map unnamed tables (like Table, Table1, Table2, etc., that match up to result sets) in order to fill the right tables. If you don't and have a pre-configured DataSet , the result sets won't match up with the DataTable s you've configured.
For simple SELECT statements just use a SqlCommandBuilder to construct the INSERT, UPDATE, and DELETE commands. It will automatically combine both the INSERT and SELECT statements for the InsertCommand property as I mentioned before. This information is all covered in the .NET Framework SDK.
This posting is provided "AS IS" with no warranties, and confers no rights.
Software Design Engineer
Developer Division Sustained Engineering
Microsoft
[My Articles] [My Blog]
|
|
|
|
|
Well i inserted at the insert of the table brands the extra sql statement
"select brand_id, name from brands" and now i get a error on the update methode
adapterBrands.Update(dS.GetChanges(), "brands");
error: "Characters found after end of SQL statement."
string ConnectionString = @"Provider=Microsoft Jet 4.0 OLE DB Provider;Data Source=C:\test\test_Techno1.mdb;";
System.Data.OleDb.OleDbConnection connection = new System.Data.OleDb.OleDbConnection(ConnectionString);
connection.Open();
string strSelectProducts = "SELECT PRODUCT_ID,NAME,PRICE,PRODUCT_CODE,BRAND FROM PRODUCTS";
string strInsertProducts = "INSERT INTO PRODUCTS (NAME,PRICE,PRODUCT_CODE,BRAND) VALUES (?, ?, ?, ?)";
System.Data.Common.DataColumnMapping[] dataColumnMappingProducts = (System.Data.Common.DataColumnMapping[]) Array.CreateInstance( typeof(System.Data.Common.DataColumnMapping), 5 );
dataColumnMappingProducts[0] = new System.Data.Common.DataColumnMapping("PRODUCT_ID","PRODUCT_ID");
dataColumnMappingProducts[1] = new System.Data.Common.DataColumnMapping("NAME,","NAME,");
dataColumnMappingProducts[2] = new System.Data.Common.DataColumnMapping("PRICE","PRICE");
dataColumnMappingProducts[3] = new System.Data.Common.DataColumnMapping("PRODUCT_CODE","PRODUCT_CODE");
dataColumnMappingProducts[4] = new System.Data.Common.DataColumnMapping("BRAND","BRAND");
OleDbTransaction transaction = null;
OleDbDataAdapter adapterProducts = new OleDbDataAdapter();
adapterProducts.SelectCommand = new OleDbCommand(strSelectProducts, connection, transaction);
adapterProducts.InsertCommand = new System.Data.OleDb.OleDbCommand(strInsertProducts, connection, transaction);
adapterProducts.TableMappings.AddRange(new System.Data.Common.DataTableMapping[] {new System.Data.Common.DataTableMapping("products", "products", dataColumnMappingProducts)});
OleDbCommandBuilder cbProducts = new OleDbCommandBuilder(adapterProducts);
DataSet dS = new DataSet();
adapterProducts.Fill(dS, "products");
adapterProducts.FillSchema(dS, System.Data.SchemaType.Mapped, "products");
adapterProducts.InsertCommand.Parameters.Add(new OleDbParameter("name", System.Data.OleDb.OleDbType.VarChar , 50 , "name"));
adapterProducts.InsertCommand.Parameters.Add(new OleDbParameter("price", System.Data.OleDb.OleDbType.Currency , 20 , "PRICE"));
adapterProducts.InsertCommand.Parameters.Add(new OleDbParameter("product_code", System.Data.OleDb.OleDbType.VarChar , 50 , "product_code"));
adapterProducts.InsertCommand.Parameters.Add(new OleDbParameter("brand", System.Data.OleDb.OleDbType.VarChar , 20 , "brand"));
string strSelectBrands = "SELECT BRAND_ID, NAME FROM BRANDS";
string strInsertBrands = "INSERT INTO BRANDS (NAME) VALUES (?);select brand_id, name from brands";
OleDbDataAdapter adapterBrands = new OleDbDataAdapter();
System.Data.Common.DataColumnMapping[] dataColumnMappingBrands = (System.Data.Common.DataColumnMapping[]) Array.CreateInstance( typeof(System.Data.Common.DataColumnMapping), 1);
dataColumnMappingBrands[0] = new System.Data.Common.DataColumnMapping("NAME","NAME");
adapterBrands.SelectCommand = new OleDbCommand(strSelectBrands, connection, transaction);
adapterBrands.InsertCommand = new System.Data.OleDb.OleDbCommand(strInsertBrands, connection, transaction);
adapterBrands.TableMappings.AddRange(new System.Data.Common.DataTableMapping[] {new System.Data.Common.DataTableMapping("brands", "brands", dataColumnMappingBrands)});
adapterBrands.InsertCommand.Parameters.Add(new OleDbParameter("name", System.Data.OleDb.OleDbType.VarChar , 50 , "name"));
OleDbCommandBuilder cbBrands = new OleDbCommandBuilder(adapterBrands);
adapterBrands.Fill(dS, "brands");
adapterBrands.FillSchema(dS, System.Data.SchemaType.Mapped, "brands");
dS.Relations.Add(dS.Tables["brands"].Columns["brand_id"], dS.Tables["products"].Columns["brand"]);
try
{
DataRow drBrand = dS.Tables["brands"].NewRow();
drBrand["name"] = "nieuwe naam";
dS.Tables["brands"].Rows.Add(drBrand);
adapterBrands.InsertCommand.Transaction = connection.BeginTransaction();
adapterBrands.Update(dS.GetChanges(), "brands"); // <--- i get a error here after inserting the "; select id, name from brands" in the sql insert statement for table brands error: "Characters found after end of SQL statement."
adapterBrands.InsertCommand.Transaction.Commit();
DataRow drProduct = dS.Tables["products"].NewRow();
drProduct["name"] = "nieuw product";
drProduct["product_code"] = "product_code";
drProduct["price"] = "7,5";
drProduct["brand"] = drBrand["brand_id"];
dS.Tables["products"].Rows.Add(drProduct);
adapterProducts.InsertCommand.Transaction = connection.BeginTransaction();
adapterProducts.Update(dS.GetChanges(), "products");
adapterProducts.InsertCommand.Transaction.Commit();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
finally
{
}
Greetings
Sander
|
|
|
|
|
Once again, the following lines will not do what you think they will:
adapterProducts.InsertCommand.Transaction = connection.BeginTransaction();
adapterProducts.Update(dS.GetChanges(), "products");
adapterProducts.InsertCommand.Transaction.Commit(); If you read the documentation for OleDbTransaction you'll see that a connection must be open for the transaction to be effective, and as I told you before (and the documentation for DataAdapter.Update also states) the DataAdapter opens and closes the connection itself. Not only are you wasting CPU cycles on useless instructions, but you'll get a false sense of security that your update is transacted.
Besides, when using a transaction you need to add a call to Rollback in the catch block to be effective.
If you want to try this, open and close the connection yourself. The default implementation of DbDataAdapter (which extends DataAdapter and from which OleDbDataAdapter directly derives) will not re-open the connection, and it will not close the connection if it didn't opened it in the first place. Create a new OleDbTransaction and associate it with your OleDbCommand s (read the documentation for OleDbTransaction because you're not using it correctly anyway). After Update complete commit it (Commit ). In the catch block roll it back (Rollback ).
After using the designer (VS.NET) to generate the commands for an OleDbDataAdapter (which I believe I recommended to you before - writing examples is always helpful) it's apparent that OLE DB does not support combined SQL expressions. Why? Probably because OLE DB is a generic API for accessing data via providers and to assume that a provider supports combined expressions would be faulty. What you'll need to do, instead, is to call DataAdapter.Fill to re-update the DataSet and/or contained DataTable s (depending on how you call Fill .
To note, the SqlCommand does support combined expressions and, if you have a choice, would be better of using SQL Server 2000 or the "free" Microsoft Data Engine (MSDE) if you have a qualifying product - Visual Studio .NET being one of them (this gives you redistribution rights as well, but be sure to read the EULA). MSDE is SQL Server 2000 but supports limited connections (20, IIRC). This gives you access to stored procedures, transaction support, replication, and so much more.
This posting is provided "AS IS" with no warranties, and confers no rights.
Software Design Engineer
Developer Division Sustained Engineering
Microsoft
[My Articles] [My Blog]
|
|
|
|
|
Does anyone know how to add text to a TextBox programaticaly without the cursor jumping to the beginning of the text?
Thanks.
avivhal
|
|
|
|
|
If you take a look at the documentation for the TextBox control you should notice a SelectionStart . Set that to TextBox.Text.Length - 1 to set the insertion point at the end of the text.
This posting is provided "AS IS" with no warranties, and confers no rights.
Software Design Engineer
Developer Division Sustained Engineering
Microsoft
[My Articles] [My Blog]
|
|
|
|
|
I want to insert the text programaticaly.
I am developing for a PDA using the .NET compact framwork.
Everytiem I add data programaticaly as follows:
textBoxTerminal.Text += (string)str;
textBoxTerminal.SelectionStart = textBoxTerminal.Text.Length;
textBoxTerminal.ScrollToCaret();
the cursor jumps to the beginning of the text and then jumps to the end.
How can I avoid this jump to the beginning of the text before I set the caret position?
Thanks.
avivhal
|
|
|
|
|
The fact that you're targeting the .NET CF is something you should've mentioned up-front. We can't help you if you don't give us all the necessary details. The other poster could've avoiding posting about the Append method if he/she knew that you were targeting .NET CF (and either knew off-hand that it wasn't available or bothered to check the documentation before giving faulty information).
Look for my answer on the other responses.
This posting is provided "AS IS" with no warranties, and confers no rights.
Software Design Engineer
Developer Division Sustained Engineering
Microsoft
[My Articles] [My Blog]
|
|
|
|
|
Thanks for the answer but I'm using the .NET compact framework in which TextBox.Append does not exist.
Any suggestions for a solution for the .NET compact framework?
Do I have to look for API native code solution?
Thanks.
avivhal
|
|
|
|
|
I'm sorry, didnt know Append wasnt available in all environments. I'm not really sure if there is a simple solution to your problem without the Append method. I'll check around because I'd swear I saw this crop up somewhere else and maybe somedoby came up with a solution that didnt involve the Append method.
I'll Let u know if I find anything.
|
|
|
|
|
Hi, Thanks for your help.
I searched all over the web and could not find a solution/idea how to solve this.
Hope you'll find a solution.
I dont think there is a simple one. I'll probably have to implement a control that uses API dll functions to fix this issue in the .net compact framework.
Please let me know if you find something.
Thanks.
avivhal
|
|
|
|
|
Would it be too "dirty" to use the clipboard and the Paste() method of your Textbox? that seems to do the job.
I dont know if Paste is available to you in your environment...never did anything with PDA's and such.
|
|
|
|
|
The SelectedText , SelectionStart , and SelectionLength properties are defined for TextBoxBase (from which TextBox derives) for the .NET CF, so you can mimic what AppendText does.
What does it do? Use ildasm.exe if you know how to read IL or get a decompiler like .NET Reflector and find out.
Basically, you're looking for something like this:
public class MyTextBox : TextBox
{
public void AppendText(string text)
{
int len = TextLength;
SelectionStart = len;
SelectionLength = len;
SelectedText = text;
}
}
This posting is provided "AS IS" with no warranties, and confers no rights.
Software Design Engineer
Developer Division Sustained Engineering
Microsoft
[My Articles] [My Blog]
|
|
|
|
|
Thanks,
I also noticed that any key event leaves the caret in its position, but when I try to add/append text programaticaly not from within a key event, the caret jumps to the beggining of the TextBox.
Is there any way to add the text from outside those events (that is not by a key clicked but by data received from other data source e.g. a serial port) and keep the caret from jumping to the beginning of the TextBox?
Thanks
avivhal
|
|
|
|
|
That's why you assign SelectionStart then SelectionLength (in that order). If that's not working for you, then you'll need to move the caret by P/Invoking SendMessage and sending EM_SETSEL message (0x00b1) to the Window handle (the Handle property on every control).
This posting is provided "AS IS" with no warranties, and confers no rights.
Software Design Engineer
Developer Division Sustained Engineering
Microsoft
[My Articles] [My Blog]
|
|
|
|
|
Great,
This should do it.
Thanks for your help.
avivhal
|
|
|
|
|
Don't you mean AppendText()? And won't it still be necessary to use SelectionStart? Something along these lines, perhaps:
private static void AddSomeTextToThisTextBoxPlease( TextBoxBase textBox, string someText )
{
int selectionStart = textBox.Text.Length;
textBox.AppendText( someText );
textBox.SelectionStart = selectionStart;
}
Or are you saying AppendText() leaves the cursor where it is? The documentation doesn't seem to say anything regarding that detail.
Matt Gerrans
|
|
|
|
|
I'm using the .net compact framework (I develop this for a pocket pc) in which AppendText does not exist.
It works fine in the full .net framework.
Aviv.
avivhal
|
|
|
|
|
AppendText is the only Append* method defined on or inheritted by TextBox , but it is not defined in the .NET CF.
Normally, no, you do not need to change the selection start since that is handled internally.
This posting is provided "AS IS" with no warranties, and confers no rights.
Software Design Engineer
Developer Division Sustained Engineering
Microsoft
[My Articles] [My Blog]
|
|
|
|
|
Sorry I did not mentioned that I was refering to the .NET CF
My mistake.
Anyhow, I get data from an serial driver I wrote for the PDA and I want to present it in the TextBox.
Since the append method does not exist and I do need to add the data received from the driver to the TextBox, I use :
TextBox.Text += RecievedText;//RecievedText is the data received from the driver
This line of code causes the caret to jump to the beggining of the TextBox.
Thanks for your reply.
avivhal
|
|
|
|
|