Populate asp labels from SQL Query - asp.net

I wrote the code to query the database, but now do not know how to get the text into my two labels 'txtTitle' & 'txtBody'
protected void GridView1_SelectedIndexChanged(object sender, EventArgs e)
{
SqlConnection thisConnection = new SqlConnection(ConfigurationManager.ConnectionStrings["blcDocumentationConnectionString"].ConnectionString);
// Create Command Object
SqlCommand nonqueryCommand = thisConnection.CreateCommand();
pnlNew.Visible = false;
pnlView.Visible = true;
try
{
// Open Connection
thisConnection.Open();
// Create SELECT statement with named parms
nonqueryCommand.CommandText = "SELECT DocumentTitle,DocumentBody FROM tblDocument WHERE DocumentID = #DocumentID";
// Add parms to Command parms collection
nonqueryCommand.Parameters.AddWithValue("#DocumentID", GridView1.SelectedValue);
// Execute query statement
nonqueryCommand.ExecuteNonQuery();
// Populate Labels
GridViewRow row = GridView1.SelectedRow;
lblTitle.Text = row.Cells[1].Text;
lblBody.Text = row.Cells[2].Text;
}
finally
{
// Close Connection
thisConnection.Close();
}
}
<asp:Panel ID="pnlView" runat="server" Visible="False" CssClass="pnlView">
<h1 style="background-color: #CCE6FF">
<asp:Label ID="lblTitle" runat="server" Text="Label"></asp:Label></h1>
<p>
<asp:Label ID="lblBody" runat="server" Text="Label"></asp:Label></p>
<p style="background-color: #EFEFEF">
<asp:Button ID="btnEdit" runat="server" Text="Edit This Document" OnClick="btnEdit_Click" /> or
cancel</p>
</asp:Panel>

Your code shows that you have a table filled with documents IDs (I'm assuming you already bound this correctly in some other part of your code)
You used the SelectedIndexChanged event correctly, but why are you executing another query inside? If executing the query is intentional, why are you binding your labels to old data? row.cells[].value holds old information, not the information you re-queried. If you want the information you re-queried for, get that info directly from the result set. Also, that result set will return nothing unless you change nonqueryCommand.ExecuteNonQuery(); to nonqueryCommand.ExecuteDataSet();

Reiterating what User:rkw mentioned above. ExecuteNonQuery will not get any data back from the database. You need to use either DataReader ( http://msdn.microsoft.com/en-us/library/haa3afyz.aspx ) or use the ExecuteDataset and put the information into a DataSet and then read from it. When you say ExecuteNonQuery you are basically telling the SQL server to execute commands but not expecting any data back from the SQL Server.

Related

SqlDataSource and stored procedure call issue

I've stumbled upon an issue and can't figure it out on my own. Hope someone could help me resolve it.
So, I have a simple stored procedure in a SQL Server 2005 database
CREATE PROCEDURE spTest
#pin varchar(128)
AS
BEGIN
SELECT #Pin as Param
END
and an asp.net page with a SqlDataSource and a GridView control in an application (VS2008)
<asp:SqlDataSource
ID="sds2"
runat="server"
ConnectionString="..."
SelectCommand="spTest"
SelectCommandType="StoredProcedure"
>
<SelectParameters>
<asp:QueryStringParameter Name="pin" QueryStringField="pin" DbType="String"/>
</SelectParameters>
</asp:SqlDataSource>
<asp:GridView ID="gv" runat="server" DataSourceID="sds2"></asp:GridView>
As you can see, the code is straightforward. Nevertheless, if I don't bother specify the pin on the url (.../Default.aspx instead of .../Default.aspx?pin=somevalue) or specify an empty line (.../Default.aspx?pin=) there is no any call to the stored procedure (I check it with SQL Server Profiler).
Moreover, if I replace the QueryStringParameter with a simple
<asp:Parameter Name="pin" DbType="String" />
and do not point out DefaultValue value, the situation repeats and no calls to the stored procedure are made. What is the reason of such a behaviour?
I'm quite a new to the asp.net and possibly overlook something, but I even tried to do the same in code-behind file programmatically instead of declaratively and the result is the same. The only thing I could find out is that in such case a Selecting event of the SqlDataSource is fired, but the Selected is not. Maybe some kind of an error happens?
Anyway, any kind of help would be greatly appreciated.
The SqlDataSource object has a property called CancelSelectOnNullParameter. Its default value is true, so I think the behavior you're seeing is expected, albeit not obvious. Try setting this property to false.
<asp:SqlDataSource
ID="sds2"
runat="server"
ConnectionString="..."
SelectCommand="spTest"
SelectCommandType="StoredProcedure"
CancelSelectOnNullParameter="false"
>
Additionally, you may find the ConvertEmptyStringToNull property of the Parameter class (QueryStringParameter extends this) to be of some use, depending on if/how your stored proc handles null values. Its default value is true as well.
Try this out.
Create a method which will return db null if parameter is not passed in the stored procedure
public static object GetDataValue(object o)
{
if (o == null || String.Empty.Equals(o))
return DBNull.Value;
else
return o;
}
Create a method which will called the stored procedure and fill the dataset.
public DataSet GetspTest(string pin)
{
try
{
DataSet oDS = new DataSet();
SqlParameter[] oParam = new SqlParameter[1];
oParam[0] = new SqlParameter("#Pin", GetDataValue(pin));
oDS = SqlHelper.ExecuteDataset(DataConnectionString, CommandType.StoredProcedure, "spTest", oParam);
return oDS;
}
catch (Exception e)
{
ErrorMessage = e.Message;
return null;
}
}
Now bind the dataset to gridview
private void GvTest()
{
DataSet oDsGvspTest = new DataSet();
string pin = Request.QueryString["Pin"];
oDsGvspTest = GetspTest(pin);
if (oDsGvspTest.Tables[0].Rows.Count > 0)
{
Gv.DataSource = oDsGvspTest;
Gv.DataBind();
}
}
Now called this method on page_load event
if(!IsPostBack)
{
GvTest();
}
If found it useful,please mark it as your answer else let me know...

How can I issue an additional select from within a repeater

I am looking for a line of code that can show how many replies a topic has in my forum. I have a repeater(REPEATER_1) to show other info about each topic, like it's title and text. For example, to get the title, I use:
<%# DataBinder.Eval(Container, "DataItem.title")%>
This works fine, but for counting replies, I need to access another table, and count all replies for this topic. I use the following SelectCommand:
"SELECT COUNT(ID) FROM [replies] WHERE parent='" & <%# DataBinder.Eval(Container, "DataItem.ID")%> & "';"
But how do I execute this SelectCommand from within the Form (and within the repeater area) of the page using <%# XXXX.. %>
I know there are alternatives using code-behind, but I am practicing doing it this way using <%# XXXX.. %>
Also, what is it called when doing script inside a form using "<%# XXXX.. %>" ? It will make it easier for me to search on the web, as google or this website cannot search for "<%#"
I would do this in the ItemDataBound event of the Repeater.
I'm following your current approach, but you should return the reply count with the query that gets the topics. Doing it the way you're doing it, you're calling the database too many times.
protected void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
// !! use a parameterized query here to avoid SQL injection
string query = String.Format("SELECT x FROM y WHERE z = {0}", DataBinder.Eval(e.Item.DataItem, "SomeColumn"));
//execute your query to get reply count
int replyCount = ExecuteQuery(query); // !! example
Label lbl = e.Item.FindControl("ReplyCountLabel") as Label;
if (lbl != null)
{
lbl.Text = replyCount.ToString()
}
}

Need help in save image in sql database using asp.net

I trying to save employee image in employee database. I have three field in database table empid, empname, empimage. Here is my database part.
CREATE DATABASE [Employee]
GO
USE [Employee]
GO
CREATE TABLE EmpDetails
(
empid int IDENTITY NOT NULL,
empname varchar(20),
empimg image
)
In the button click event, i have written the following code:
SqlConnection connection = null;
try
{
FileUpload img = (FileUpload)imgUpload;
Byte[] imgByte = null;
if (img.HasFile && img.PostedFile != null)
{
//To create a PostedFile
HttpPostedFile File = imgUpload.PostedFile;
//Create byte Array with file len
imgByte = new Byte[File.ContentLength];
//force the control to load data in array
File.InputStream.Read(imgByte, 0, File.ContentLength);
}
// Insert the employee name and image into db
string conn = ConfigurationManager.ConnectionStrings["EmployeeConnString"].ConnectionString;
connection = new SqlConnection(conn);
connection.Open();
string sql = "INSERT INTO EmpDetails(empname,empimg) VALUES(#enm, #eimg)SELECT ##IDENTITY";
SqlCommand cmd = new SqlCommand(sql, connection);
cmd.Parameters.AddWithValue("#enm", txtEName.Text.Trim());
cmd.Parameters.AddWithValue("#eimg", imgByte);
int id = Convert.ToInt32(cmd.ExecuteScalar());
lblResult.Text = String.Format("Employee ID is {0}", id);
}
catch
{
lblResult.Text = "There was an error";
}
finally
{
connection.Close();
}
And Here is my form:
<asp:Label ID="lblEmpName" runat="server" Text="Employee Name"></asp:Label>
<asp:TextBox ID="txtEName" runat="server"></asp:TextBox>
<br />
<asp:Label ID="lblImage" runat="server" Text="Employee Image"></asp:Label>
<asp:FileUpload ID="imgUpload" runat="server" />
<br />
<br />
<asp:Button ID="btnSubmit" runat="server" Text="Submit"
onclick="btnSubmit_Click" />
&nbsp
<asp:Label ID="lblResult" runat="server" ForeColor="#0066FF"></asp:Label>
<br />
<hr />
<asp:Image ID="Image1" style="width:200px" Runat="server" />
But when I am uploading any image and clicking on submit button getting this error "Object reference not set to an instance of an object." Pls somebody point out my error.
Thanks,
Sumit
Object Reference errors only occur when an object is not initialized and you try to reference it. This could be any object you are referencing within your code. If you step through the code while debugging, you can see exactly which reference is null.
You have an if statement that initializes the imgByte object:
imgByte = new Byte[File.ContentLength];
If the img object turns out to be null, that code does not run. Then you reference the imgByte here, regardless of whether or not the img was null:
cmd.Parameters.AddWithValue("#eimg", imgByte);
Check the the HttpPostedFile object itself is not null and move your imgByte object initialization outside the if statement. Also, the name File is already used by the System.IO.File object. You may want to rename it just to be safe.
I would rearrange your ADO.NET code a bit - make it safe and more reliable; also, I would make sure to separate the two SQL statements in your "sql" string by a semicolon to make it clear to SQL that this is two commands, really:
string conn = ConfigurationManager.ConnectionStrings["EmployeeConnString"].ConnectionString;
using(connection = new SqlConnection(conn))
{
string sqlStmt = "INSERT INTO dbo.EmpDetails(empname, empimg) " +
"VALUES(#enm, #eimg); SELECT ##IDENTITY";
using(SqlCommand cmd = new SqlCommand(sqlStmt, connection))
{
cmd.Parameters.AddWithValue("#enm", txtEName.Text.Trim());
cmd.Parameters.AddWithValue("#eimg", imgByte);
connection.Open();
int id = Convert.ToInt32(cmd.ExecuteScalar());
connection.Close();
lblResult.Text = String.Format("Employee ID is {0}", id);
}
}
Any luck with this?? Otherwise you should really step through the code in the debugger and see where in your code you reference something that is NULL (and you don't check for that condition).
Marc
While i am debugging this code i am
getting exception in this
line..."string conn =
ConfigurationManager.ConnectionStrings["EmployeeConnString"].ConnectionString;"
Exception is: Object reference not set
to an instance of an object.
You need to add a connection string named EmployeeConnString to web.config.
Your exception handler does not distinguish where exactly an exception occurred, and issues a single error message for any possible error.

Error: SelectedValue which is invalid because it does not exist in the list of items

I have a Gridview which binds to an ObjectDataSource (objStudentDetails). In edit/insert mode of the Gridview one of the fields is a DropDownList that gets it's pick list options from a lookup table. I have this DropDownList binding to another ObjectDataSource control (objStateList) which represents the lookup table. It works fine as long as the value in the objStudentDetails ObjectDataSource matches one of the values in the objStateList ObjectDataSource, at least in the case of a non empty string value anyway.
The objStateList has these values (from the stored proc that loads it - ID#6 is an empty string ''):
StateId State
----------- -----
6
4 AL
1 GA
3 KY
2 TN
The objStudentDetails has these values (from the stored proc that loads it):
FirstName LastName State
----------- ---------- -----
tone smith TN
Or it could have this result set (State is an empty string - ''):
FirstName LastName State
----------- ---------- -----
jenny johnson
In the first objStudentDetails resultset the state DropDownList in the EditItemTemplate shows up fine. In the second resultset, however, I get this error:
'ddlEditState' has a SelectedValue which is invalid because it does not exist in the list of items.
Parameter name: value
I would think that since my lookup table has a value with an empty string, that the objStudentDetails value with an empty string for state would match, but something isn't working the way I am expecting it to.
Here is my EditItemTemplate code from the Gridview:
<EditItemTemplate>
<asp:Panel ID="panEditState" runat="server">
<asp:DropDownList ID="ddlEditState" runat="server" CssClass="GridviewDropdownlist"
DataSourceID="objStateList" DataTextField="State" DataValueField="State"
SelectedValue='<%# Bind("State") %>'
Width="50px">
</asp:DropDownList>
</asp:Panel>
</EditItemTemplate>
And the objStateList, which calls a method passing a parameter of which lookup table to query:
<asp:ObjectDataSource ID="objStateList" runat="server" SelectMethod="GetDropdownData" TypeName="AIMLibrary.BLL.DropdownData">
<SelectParameters>
<asp:Parameter Name="itemsToGet" DefaultValue="state" />
</SelectParameters>
</asp:ObjectDataSource>
Any ideas?
Start by setting both DropDownLists' AppendDataBoundItems property to true. Next, add the NULL ListItem by adding the following <asp:ListItem> element to each DropDownList so that the declarative markup looks like:
<asp:DropDownList ID="Categories" runat="server"
DataSourceID="CategoriesDataSource" DataTextField="CategoryName"
DataValueField="CategoryID" SelectedValue='<%# Bind("CategoryID") %>'
AppendDataBoundItems="True">
<asp:ListItem Value="">[nothing selected]</asp:ListItem>
</asp:DropDownList>
I suspect there are many different scenarios that can cause this error. In my case, I had a drop down placed in a template field. The drop down was bound to its own objectdatasource, and its selectedvalue property was bound to a field from the gridview's own (separate) datasource.
Now, with my specific scenario, the problem was a race condition. The gridview's datasource was being populated and bound BEFORE the dropdowns had their turn. This also meant that the dropdowns' selectedvalues were being set BEFORE the dropdowns' items had been created through their own bindings.
I'm sure there's got to be a better solution, but I didn't have much time for research. I disconnected the gridview and the dropdowns from their datasources (meaning, removing the assignments from the designer) and opted bind programmatically. That way, I can explicitly bind the dropdowns so that their items' values will be available when the gridview itself is bound.
So far, so good. Just a few extra lines of code in the Page_Load
AppendDataBoundItems="True"> works but not in all cases. Making dropdownlist inside GridView is still a mystery which Microsoft has to resolve. They say development is ASP is much quicker than PHP. Well this is my third day on this small problem and still have no solution.
OK, since this is a common problem I guess its worth to actually post an answer: After a lot of looking around I've found two solutions - well, one patch and one real one.
Patching:
Set the DDL setting AppendDataBoundItem=true anda add manually one element to the list (i.e. "Please Select" with null value):
< asp:DropDownList ID="DropDownList5 runat="server" AppendDataBoundItems="True" ... >
< asp:ListItem>Please Select< /asp:ListItem>
< /asp:DropDownList>
This seems to work in about 80% of cases. I had a weird situation when I had to upgrade existing (and working) query used by DDL to allow another value of parameter - Query was something similar to SELECT ID, Name from EMPLOYEES where Department =#Department and originally #Department could only be equal to "Planners" and "Workshop" - after adding "Logistics" DDL mysteriously stopped working ONLY for the new value of department.
Proper solution: Bind the DDL during the GridView_RowDataBound event (fount thanks to This article
My parameter is taken as a text from the label (set up somewhere else)
protected void GridView5_RowDataBound(object sender, GridViewRowEventArgs e)
{
//********** this is a workaround for the annoying problem with dropdownlist in gidview without adding new item ************
if (e.Row.RowType == DataControlRowType.DataRow && GridView5.EditIndex == e.Row.RowIndex)
{
DropDownList DropDownList5 = (DropDownList)e.Row.FindControl("DropDownList5");
string query = "SELECT gkey as empID, name FROM [employees] where department=#department";
SqlCommand command = new SqlCommand(query);
command.Parameters.AddWithValue("#department", lblDepartment.Text);
DropDownList5.DataSource = GetData(command);
DropDownList5.DataTextField = "name";
DropDownList5.DataValueField = "empID";
DropDownList5.DataBind();
}
And the GetData method:
private DataTable GetData (SqlCommand cmd)
{
string strConnString = ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString;
using (SqlConnection con = new SqlConnection(strConnString))
{
using (SqlDataAdapter sda = new SqlDataAdapter())
{
cmd.Connection = con;
sda.SelectCommand = cmd;
using (DataTable dt= new DataTable())
{
sda.Fill(dt);
return dt;
}
}
}
}

How would I search through a DataSet and change data in it before it gets bound?

Try
Dim ds As DataSet = SqlHelper.ExecuteDataset(ConfigurationManager.ConnectionStrings("connstr").ConnectionString, CommandType.StoredProcedure, "Get_All", New SqlParameter("#userid", Session("userid")))
rptBundles.DataSource = ds.Tables(0)
Catch ex As Exception
showerror(ex, Me)
End Try
That is the code, I want to be able to parse through it and find certain rows that have a certain boolean set to 1 and then edit other variables in that row accordingly, how would I do this, I tried making a For Each row nested in a For Each table but when I tested it the repeater never populates with data...
For Each ds_table As DataTable In ds.Tables
For Each ds_row As DataRow In ds_table.Rows
If ds_row("isScorm") = 1 Then
ds_row("totalLessons") = 100
ds_row("TotalQuestions") = 100
ds_row("lessonscompleted") = 50
ds_row("TotalCorrect") = 50
End If
Next
Next
Only when I remove that code does the repeater populate as expected, but I got no errors!
If you're using a Repeater, or whatever datasource bound control, I would use the ItemDataBound event and set those values to your controls.
If this was your basic HTML
<html>
<asp:Repeater id="repeater" runat="server" OnItemDataBound="repeater_ItemDatabound">
<ItemTemplate>
<span><%# DataBinder.Eval(Container.DataItem, "isScorm") %></span>
<span id="totalLessonsSpan" runat="server"><%# DataBinder.Eval(Container.DataItem, "totalLessons") %></span>
</ItemTemplate>
</asp:Repeater>
</html>
I would have this in the code behind
protected void repeater_ItemDatabound(object sender, RepeaterItemEventArgs e)
{
DataRow row = e.Item.DataItem as DataRow;
if (row == null) { }
else
{
int isScorm = 0;
int.TryParse(Convert.ToString(row["isScorm"]), out isScorm);
if (isScorm > 0)
{
HtmlGenericControl totalLessonsSpan = e.Item.FindControl("totalLessonsSpan") as HtmlGenericControl;
totalLessonsSpan.Text = "100";
}
}
}
You probably don't want to loop through the data and swap it there, then bind when you can do it during the bind.
Alternately, something I hate that DB's do because of my need for data integrity, is change it in your SQL select with case statements.
Does adding rptBundles.DataBind() after setting DataSource fix the problem?
Also, you might want to check out the DataTable.Select method to only select (and then modify) rows where isScorm = 1.

Resources