Gridview not updating table when column/cell starts with no data - asp.net

UPDATED: Here is the SP, it doesn't match exactly because of ongoing testing, but you get the jist. Some fields are commented out because of testing....
#tableName Varchar(150),
#new_lang_String nvarchar(max),
-- #lang_String nvarchar(max),
#ID int,
#prev_LangString nvarchar(max) = NULL,
#original_lang_String nvarchar(max) = NULL,
#brief_Descrip nvarchar(max) = NULL,
#submittedBy nvarchar(250) = NULL
AS
/* SET NOCOUNT ON */
DECLARE #lang_String varchar(max);
SET #prev_LangString = #new_lang_String;
DECLARE #submitDate1 DATETIME;
SET #submitDate1 = GETDATE();
DECLARE #sql varchar(max);
SET #lang_String = #original_lang_String;
BEGIN
SET #sql = 'UPDATE ' + #tableName + ' SET [lang_String] = ''' + COALESCE(#lang_String, NULL) + ''', [date_Changed] = ''' + convert(varchar(20), #submitDate1) + ''', [prev_LangString] = ''' + COALESCE(#prev_LangString, NULL) + ''', [brief_Descrip] = ''' + COALESCE(#brief_Descrip, NULL) + ''', [submittedBy] = ''' + #submittedBy + '''
WHERE (ID = ' + CAST(#ID as nvarchar(10)) + '); '
EXECUTE(#sql);
END
RETURN
As you can probably tell in the code I have been struggling with handling the Null in some of the fields as well. Hence the default values inteh update parameters of = " " on some fields.
I am using a gridview to display information that is retrieved from a table in a SQL Express DB. When the user clicks EDIT, and enters information, I am trying to update the table with a STORED PROCEDURE called from the Gridview. See aspx code below.
The issue is that the column which is being edited will not update the DB table unless it had previously had data stored in it, as in the cell in the column IS NOT Null. No errors.
Since most cells in this column are Null to begin with, no data is getting updated. No errors, just nothing written to the table. If the table previously had data within the column cell in question it can be succesfully edited and updated.
Gridview from ASPX Page....
<asp:BoundField DataField="lang_String" HeaderText="Foreign Text" SortExpression="lang_String">
<ControlStyle Width="400px"/>
</asp:BoundField>
Update Command on Gridview calls SP, which works, provided column/cell already had data...
UpdateCommand="EXEC usp_UpdatePTEdit #tableName, #lang_String=#lang_String, #ID=#original_ID, #prev_LangString=#original_lang_String, #brief_Descrip=#brief_Descrip, #submittedBy=#SubmittedBy">
Parameters passed to UpdateCommand, only using a few...
<UpdateParameters>
<asp:SessionParameter Name="tableName" SessionField="tableName1" />
<asp:SessionParameter Name="submittedBy" SessionField="SubmittedByUser" />
<asp:Parameter Name="data_text" Type="String" />
<asp:Parameter Name="lang_String" Type="String" DefaultValue=" " />
<asp:Parameter Name="date_Changed" Type="DateTime" />
<asp:Parameter Name="prev_LangString" Type="String" DefaultValue=" " />
<asp:Parameter Name="needsTranslation" Type="String" />
<asp:Parameter Name="displayRecord" Type="String" />
<asp:Parameter Name="brief_Descrip" Type="String" DefaultValue=" " />
<asp:Parameter Name="original_ID" Type="Int32" />
<asp:Parameter Name="original_data_text" Type="String" />
<asp:Parameter Name="original_lang_String" Type="String" />
<asp:Parameter Name="original_date_Changed" Type="DateTime" />
<asp:Parameter Name="original_prev_LangString" Type="String" />
<asp:Parameter Name="original_needsTranslation" Type="String" />
<asp:Parameter Name="original_displayRecord" Type="String" />
<asp:Parameter Name="original_brief_Descrip" Type="String" />
<asp:Parameter Name="original_submittedBy" Type="String" />
</UpdateParameters>
Everything works if the cell originally has data, "original_lang_String" but if it has not been populated, I can not use the Edit operation of the Gridview to successfully update the table.
Any help or suggestions would be appreciated.

#prev_LangString=#original_lang_String
Depending on what is in usp_UpdatePTEdit, I bet it's failing because somewhere it's checking for an original value that doesn't exist. NULL is special and equality checks for it fail.
Post the code that is in usp_UpdatePTEdit stored proc for more help.

I think the problem may be with the assignment of the parameters to the column of the same name (#lang_String=#lang_String). I recommend specifying the parameters in the order that they appear in the stored proc and remove the #name= syntax. I think that is just going to get the datasource or grid view confused.
Update
I think that you would be better off changing the UpdateCommand to:
UpdateCommand="usp_UpdatePTEdit"
and adding:
UpdateCommandType="StoredProcedure"
This seems to be a better fit for how the update command is designed to work.

Related

SqlDataSource UpdateParameters - Input string was not in a correct format

I have inherited some ASP.NET code that I need to update which has resulted in my needing to change the ASP SqlDataSource's UpdateCommandType from a string (hard coded SQL Update statement) to a stored procedure containing the Update statement.
The string executes fine and uses parameters that are bound to controls in a details view (I know this is not best practice and it pains me having to work with data connections from the client side...! But I dont have time to re-write all the data connections for this and many pages just yet).
Anyway, I have just changed the UpdateCommand to a stored procedure that does the same thing and I just get the error
Input String was not in a correct format.
when I try to update on the page.
I can supply code if requested, but it is big & horrible so I am tentatively asking if anyone has any initial ideas? I will put a few small bits below though. I have been looking at the UpdateParameterCollection as I wonder if the parameter collection is getting cached anywhere - but cannot see anything.
I have controls bound to the DataSource items like so:
<EditItemTemplate>
<asp:CheckBox ID="chkNonReview" runat="server" Checked='<%# Bind("NonReview") %>' />
</EditItemTemplate>
And the SqlDataSource has been changed from this...
<asp:SqlDataSource ID="dsEventDV" runat="server"
ConnectionString="<%$ ConnectionStrings:MyConnString %>"
DeleteCommand="DELETE FROM [I_TRAINEE_EVENTS] WHERE [EVENTID] = #EVENTID"
InsertCommand="INSERT_TRAINEE_EVENTS_ED3"
InsertCommandType="StoredProcedure"
OnInserted="DSEvent_Inserted"
SelectCommand="Get_Candidate_Events_I3"
SelectCommandType="StoredProcedure"
UpdateCommand="UPDATE I_TRAINEE_EVENTS (etc...)"
.....
to this:
<asp:SqlDataSource ID="dsEventDV" runat="server"
ConnectionString="<%$ ConnectionStrings:MyConnString %>"
DeleteCommand="DELETE FROM [I_TRAINEE_EVENTS] WHERE [EVENTID] = #EVENTID"
InsertCommand="INSERT_TRAINEE_EVENTS_ED3"
InsertCommandType="StoredProcedure"
OnInserted="DSEvent_Inserted"
SelectCommand="Get_Candidate_Events_I3"
SelectCommandType="StoredProcedure"
UpdateCommand="UPDATE_TRAINEE_EVENTS"
UpdateCommandType="StoredProcedure">
.....
With the new UpdateCommand values.
The update parameters:
<UpdateParameters>
<asp:Parameter Name="EVENTID" Type="Int32"/>
<asp:Parameter Name="EVENTTYPEID" Type="Int32"/>
<asp:Parameter Name="EVENTDATE" Type="DateTime"/>
<asp:Parameter Name="STAFFID" Type="Int32"/>
<asp:Parameter Name="REVIEWNO" Type="Int32"/>
<asp:Parameter Name="COMMENTS" Type="String"/>
<asp:Parameter Name="DESTINYVERIFIED" Type="Int32"/>
<asp:Parameter Name="DESTINYVERIFIEDBY" Type="Int32"/>
<asp:Parameter Name="DESTINYVERIFIEDDATE" Type="DateTime"/>
<asp:Parameter Name="REASONFORSUSPENSIONID" Type="Int32"/>
<asp:Parameter Name="RETURNTOWORKDATE" Type="DateTime"/>
<asp:Parameter Name="ContactDetailsUpdated" Type="Int32"/>
<asp:Parameter Name="RETENTION_STATUS_ID" Type="Int32"/>
<asp:Parameter Name="RETENTION_REASON_ID" Type="Int32"/>
<asp:Parameter Name="NonReview" Type="Int32"/>
<asp:Parameter Name="FalsifiedEventReason" Type="Int32"/>
<asp:Parameter Name="SusReqReasonID" Type="Int32"/>
<asp:Parameter Name="SusReqReturnDate" Type="DateTime"/>
</UpdateParameters>
The stored procedure declaration is as follows:
CREATE PROCEDURE [dbo].[UPDATE_TRAINEE_EVENTS]
#EVENTID int,
#EVENTTYPEID int,
#EVENTDATE datetime,
#STAFFID int,
#REVIEWNO int,
#COMMENTS varchar(2100),
#DESTINYVERIFIED int,
#DESTINYVERIFIEDBY int,
#DESTINYVERIFIEDDATE datetime,
#REASONFORSUSPENSIONID int,
#RETURNTOWORKDATE datetime,
#ContactDetailsUpdated int,
#RETENTION_STATUS_ID int,
#RETENTION_REASON_ID int,
#NonReview int,
#FalsifiedEventReason int,
#SusReqReasonID int,
#SusReqReturnDate datetime
AS
......
I have also run SQL Server Profiler against the session to see what was being passed to the database, however the error comes in before anything hits the database which appears to suggest the problem is within the ASP.NET side of things.
Your <asp:Parameter Name="EVENTID" /> should have a datatype.
I think it should be like this..
<asp:Parameter Name="EVENTID" Type="Int32" />

Procedure or function 'xyz' has too many arguments specified

I know this type of question has been asked at least a dozen times on SO, but I've gone through all the previous questions and answers I could find here and none that I have found apply. I am using several FormView objects on my page and now want to add the option to edit one of them. The FormView is populated by SqlDataSource linked to a stored procedure, so I made a stored procedure to update the records and added it to the SqlDataSource, which now looks like this:
<asp:SqlDataSource ID="TestSqlDataSource" runat="server"
SelectCommandType="StoredProcedure"
ConnectionString="<%$ ConnectionStrings:development %>"
SelectCommand="usp_GetNewTestDetails"
UpdateCommand="usp_UpdateTest"
UpdateCommandType="StoredProcedure"
onupdating="TestSqlDataSource_Updating">
<SelectParameters>
<asp:SessionParameter SessionField="TestID" Name="TestID"/>
</SelectParameters>
<UpdateParameters>
<asp:Parameter Name="testId" Type="Int32"/>
<asp:Parameter Name="testerLicense" Type="Int32" />
<asp:Parameter Name="premiseOwner" Type="String" />
<asp:Parameter Name="premiseAddress" Type="String" />
<asp:Parameter Name="premiseCity" Type="String" />
<asp:Parameter Name="premiseState" Type="String" />
<asp:Parameter Name="premiseZip" Type="String" />
<asp:Parameter Name="protectionType" Type="String" />
<asp:Parameter Name="testType" Type="String" />
<asp:Parameter Name="repairs" Type="String" />
<asp:Parameter Name="notes" Type="String" />
<asp:Parameter Name="testDate" Type="DateTime" />
<asp:Parameter Name="employerName" Type="String" />
<asp:Parameter Name="employerAddress" Type="String" />
<asp:Parameter Name="phoneNumber" Type="String" />
<asp:Parameter Name="emailAddress" Type="String" />
<asp:Parameter Name="dataEntryName" Type="String" />
<asp:Parameter Name="dataEntryPhone" Type="String" />
<asp:Parameter Name="signature" Type="String" />
<asp:Parameter Name="entryDate" Type="DateTime" />
</UpdateParameters>
</asp:SqlDataSource>
When I attempt to update a record, I'm getting an error that says there are too many parameters in my query. I have triple checked that the parameters in my code match exactly (name, number, and even order) to the ones in my stored procedure.
In attempting to find answers, I came across this post which referenced this site (had to go to archive.org because the original appears to be down). I applied what they suggested for adding the parameters to the trace function. What I found was that in my stored procedure, there are a few "lookup" values from the select procedure that aren't in the update procedure. The table I'm trying to update only has the ID of the tester, but the users would like to see their name as well, so it references that table, but in the FormView those fields are read-only during edit mode so they can't attempt to change it. All the other parameters line up... only those lookup values are off.
I thought that by including the specific list of parameters to pass that it would only use those parameters, but that appears to be incorrect. Now I'm stumped because I have already specified the parameters, and I can't see anywhere that they are being overwritten with the ones from the select stored procedure. Where do I tell it not to use those read-only values?
I don't want to remove them from the original stored procedure because they will be needed by the users. The one workaround that I have come up with so far is to add them to the stored procedure and then just never use them. Although I'm fairly certain this would work, it is very much just covering up the problem rather than fixing it.
EDIT: Additional code, per request
This is the method that outputs the parameters to the trace function:
protected void TestSqlDataSource_Updating(object sender, SqlDataSourceCommandEventArgs e)
{
for (int i = 0; i < e.Command.Parameters.Count; i++)
{
Trace.Write(e.Command.Parameters[i].ParameterName);
if (e.Command.Parameters[i].Value != null)
{
Trace.Write(e.Command.Parameters[i].Value.ToString());
}
}
}
This is the stored procedure used for updating:
ALTER PROCEDURE [dbo].[usp_UpdateTest]
#testId INT ,
#testerLicense INT ,
#premiseOwner VARCHAR(50) ,
#premiseAddress VARCHAR(150) ,
#premiseCity VARCHAR(50) ,
#premiseState VARCHAR(2) ,
#premiseZip VARCHAR(10) ,
#protectionType VARCHAR(11) ,
#testType VARCHAR(2) ,
#repairs VARCHAR(200) ,
#notes VARCHAR(300) ,
#testDate DATETIME ,
#employerName VARCHAR(50) ,
#employerAddress VARCHAR(150) ,
#phoneNumber VARCHAR(25) ,
#emailAddress VARCHAR(60) ,
#dataEntryName VARCHAR(50) ,
#dataEntryPhone VARCHAR(25) ,
#signature VARCHAR(50) ,
#entryDate DATETIME
AS
BEGIN
SET NOCOUNT ON;
UPDATE dbo.Tests
SET TesterLicense = #testerLicense ,
PremiseOwner = #premiseOwner ,
PremiseAddress = #premiseAddress ,
PremiseCity = #premiseCity ,
PremiseState = #premiseState ,
PremiseZip = #premiseZip ,
ProtectionType = #protectionType ,
TestType = #testType ,
Repairs = #repairs ,
Notes = #notes ,
TestDate = #testDate ,
EmployerName = #employerName ,
EmployerAddress = #employerAddress ,
PhoneNumber = #phoneNumber ,
EmailAddress = #emailAddress ,
DataEntryName = #dataEntryName ,
DataEntryPhone = #dataEntryPhone ,
Signature = #signature ,
EntryDate = #entryDate
WHERE TestID = #testId
END
Ended up figuring this out on my own. It was related to the fact that Visual Studio created the templates for me based on the stored procedure's schema. When the templates are autogenerated, every textbox in the <EditItemTemplate> section gets generated like this:
<asp:TextBox ID="TestIDTextBox" runat="server" Text='<%# Bind("TestID") %>'/>
Turns out that it is the Bind statement that caused this. VS automatically creates a parameter for any field populated using Bind. Although I was led to believe that the <UpdateParameters> section should have overridden this, it was actually the other way around. I was able to prevent these few read-only fields from passing back their parameters by changing the code on those fields from Bind to Eval:
<asp:TextBox ID="TestIDTextBox" runat="server" Text='<%# Eval("TestID") %>'/>
Works perfectly now.
Addendum:
Found that this causes the same problem in the other direction as well. If you mark a field you don't want edited as Eval but it needs to be included in the update (such as a row ID) it will not work, this time for too few parameters. I'm wondering now what the purpose of the <UpdateParameters> section even is, since it doesn't seem to follow anything in there...
You can delete unwanted parameters during e.g OnDeleting event (e.Command.Parameters.RemoveAt(i)).

Deleting from SQL detailsView

Hey I am just learning to how to use asp.net and I am trying to use the grid view to display information and details view edit/delete the information from the database. Right now I can edit and update the information in the database but I also want it to delete and something is not working for me. I set up an exception and when I select the item and press delete it pops up my exception that another user has deleted the item when it hasn't. Im not really sure what i have done wrong, to me it looks like it should work.
Here is the code for the delete command and parameters from the details view
DeleteCommand="DELETE FROM [Customers]
WHERE [CustomerID] = #original_CustomerID
AND [Name] = #original_Name
AND [Address] = #original_Address
AND [City] = #original_City
AND [State] = #original_State
AND [ZipCode] = #original_ZipCode
AND ([Phone] = #original_Phone
OR [Phone] IS NULL AND #original_Phone IS NULL)
AND ([Email] = #original_Email
OR [Email] IS NULL AND #original_Email IS NULL)"
<DeleteParameters>
<asp:Parameter Name="original_CustomerID" Type="Int32" />
<asp:Parameter Name="original_Name" Type="String" />
<asp:Parameter Name="original_Address" Type="String" />
<asp:Parameter Name="original_City" Type="String" />
<asp:Parameter Name="original_State" Type="String" />
<asp:Parameter Name="original_ZipCode" Type="String" />
<asp:Parameter Name="original_Phone" Type="String" />
<asp:Parameter Name="original_Email" Type="String" />
</DeleteParameters>
and here is the delete functions in the cs file
protected void DetailsView1_ItemDeleted(object sender, DetailsViewDeletedEventArgs e)
{
if (e.Exception != null)
{
lblError.Text = "A database error has occurred.<br /><br />" +
"Message: " + e.Exception.Message;
e.ExceptionHandled = true;
}
else if (e.AffectedRows == 0)
lblError.Text = "Another user may have deleted that customer."
+ "<br />Please try again.";
else
GridView1.DataBind();
}
protected void DetailsView1_ItemDeleting(
object sender, DetailsViewDeleteEventArgs e)
{
e.Values["Name"]
= e.Values["Name"].ToString().Substring(1);
}
Why do you have such a huge query for a delete statement?Have a look how it's done in the MSDN DetailsView example
The CustomerID in your SQL table should be unique so your delete statement should be as simple as:
DeleteCommand="DELETE FROM [Customers] WHERE [CustomerID] = #original_CustomerID"
And only one delete parameter:
<DeleteParameters>
<asp:Parameter Name="original_CustomerID" Type="Int32" />
</DeleteParameters>
One more thing which is quite important is you need to set DataKeyNames="CustomerID" on the DetailsView so that DetailsView1_ItemDeleted knows which row to delete. Hope this helps!

ASP.NET UpdateCommand with multiple tables updates

I am using ASP.NET and using a grid with the UpdateCommand to update 2 tables
I have the following but doesn't seem to work as I do not get any errors but it simply does not update. From what you can see, am I on the right track?
UpdateCommand="UPDATE [tbl_ProgDt] SET [Type] = #type, [Identifiction] = #samplePoint WHERE [Seq] = #valID UPDATE [tbl_Prog] SET StoreNum = #storeNum WHERE ID = (SELECT ID FROM [tbl_ProgDt] WHERE [Seq] = #valID " >
<UpdateParameters>
<asp:Parameter Name="type" Type="String" />
<asp:Parameter Name="samplePoint" Type="String" />
<asp:Parameter Name="valID" Type="Int32" />
<asp:Parameter Name="storeNum" Type="Int32" />
<asp:Parameter Name="valID" Type="Int32" />
</UpdateParameters>
If you need to do something like that, it would be better to create a stored procedure and wrap the two update sentences using a database transaction
You need to specify:
UpdateCommandType="StoredProcedure" UpdateCommand="Stored Procedure Name"
In your Stored Procedure, something like this:
BEGIN TRANSACTION;
-- your update sentences
COMMIT TRANSACTION;

SWL Error Function has too many arguments specified

I am using ASP.NET 3.5 and SQL Server 2008.
I have a SQLDataSource & Gridview. I am trying to update 2 tables at the same time using a stored procedure in SQL.
SQLDatasource is passing 7 parameters.
5 parameters that the stored procedaure needs, Return value & StudentID.
Not sure if the error is in my SQLDatasorce or my stored procedure.
Here's my ASPX Code:
<asp:SqlDataSource ID="sqldsUserLoginNLevels" runat="server"
ConnectionString="<%$ ConnectionStrings:QuizStarConnectionString %>"
SelectCommand="SELECT UserLogins.StudentID, UserLogins.StudentName, UserLogins.UserID,
UserLogins.Password, UserLevels.GrammarStart, UserLevels.GrammarCurrent,
UserLevels.MathStart, UserLevels.MathCurrent
FROM UserLogins
INNER JOIN UserLevels ON UserLogins.StudentID = UserLevels.StudentID"
DeleteCommand="DELETE FROM [UserLogins] WHERE [StudentID] = #original_StudentID"
InsertCommand="INSERT INTO [UserLogins] ([StudentName], [UserID], [Password])
VALUES (#StudentName, #UserID, #Password)"
UpdateCommand="UpdateUserLoginsAndUserLevels"
UpdateCommandType="StoredProcedure" >
<DeleteParameters>
<asp:Parameter Name="original_StudentID" />
</DeleteParameters>
<UpdateParameters>
<asp:Parameter Name="StudentName" Type="String" />
<asp:Parameter Name="UserID" Type="String" />
<asp:Parameter Name="Password" Type="String" />
<asp:Parameter Name="GrammarStart" Type="String" />
<asp:Parameter Name="MathStart" Type="String" />
<asp:Parameter Direction="ReturnValue" Name="RETURN_VALUE" Type="Int32" />
</UpdateParameters>
<InsertParameters>
<asp:Parameter Name="StudentName" Type="String" />
<asp:Parameter Name="UserID" Type="String" />
<asp:Parameter Name="Password" Type="String" />
</InsertParameters>
</asp:SqlDataSource>
My Stored Procedure is:
ALTER PROCEDURE [dbo].[UpdateUserLoginsAndUserLevels] (
#StudentName VARCHAR(50),
#UserID NCHAR(10),
#Password NCHAR(10),
#GrammarStart NCHAR(10),
#MathStart NCHAR(10))
AS
DECLARE #StudentID INT;
BEGIN Transaction
BEGIN TRY
SELECT * From UserLogins
Where StudentID = #StudentID
UPDATE UserLogins
SET
StudentName= #StudentName,
UserID = #UserID,
Password = #Password
Where StudentID = #StudentID
UPDATE UserLevels
SET
GrammarStart= #GrammarStart,
MathStart = #MathStart
FROM UserLevels
INNER JOIN UserLogins ON UserLogins.StudentID = UserLevels.StudentID
WHERE (UserLevels.StudentID = #StudentID)
END TRY
BEGIN CATCH
DECLARE #ErrorMessage NVARCHAR(4000), #ErrorSeverity INT
-- Assign variables to error-handling functions that
-- capture information for RAISERROR.
SELECT #ErrorMessage = ERROR_MESSAGE(), #ErrorSeverity = ERROR_SEVERITY()
-- Rollback the failed transaction
ROLLBACK;
-- Raise an error: with the original error information.
RAISERROR(#ErrorMessage, #ErrorSeverity, 1);
END CATCH
COMMIT Transaction;
Have't figured how to post code yet. Sorry.
Make sure you are not double adding parameters. Since you are adding them in the aspx page you do not need to add them in your code behind.
For example if your code behind has this in it:
sqldsUserLoginNLevelsUserID.UpdateParameters.Add(new Parameter("UserID ", TypeCode.Int32));
It could explain your error.
If you need to set the value from code behind do it like this:
sqldsUserLoginNLevelsUserID.UpdateParameters["UserID "].DefaultValue = "1";

Resources