How to show fixed amount of rows in asp.net gridview - c#

So here I have few gridviews in a row in asp.net. The problem now is it is inconsistent where some gridview would have 5 data and some would have 10. It looks ugly and since I needed to print. It's crucial.
I wanted to show max 15 rows. It is databound from the database which the user would fill up the subjects taken form(up to 15 rows). And if any of the rows doesn't have any of the data. It would leave it blank instead(note that the database didn't fills up to 15 rows.. only what is entered by the user). I've done some research but only found a few that might be related but using javascipt/changing current SQL given. I'm not allowed to use any javascript in the site (supports later would be a problem). And since I'm an intern. The sql code is given to me. I just need to implement it. What can I do to show fixed amount of rows in gridview? Is there any attribute that I can use in gridview to fill up the empty space to 15 rows?
aspx file
<asp:GridView ID="GridViewResult" runat="server" AutoGenerateColumns="False" EmptyDataText="NO RECORD" Font-Size="Small"
GridLines="Both" CellPadding="1" Height="101px" Width="100%" ShowFooter="True">
<Columns>
<asp:TemplateField HeaderText="Subjects">
<ItemTemplate>
<asp:Label ID="lbl" runat="server" Text='<%# Eval("Subjects") %>'></asp:Label>
</ItemTemplate>
<ItemStyle HorizontalAlign="Center" Width="25px" />
</asp:TemplateField>
<asp:TemplateField HeaderText="Grade">
<ItemTemplate>
<asp:Label ID="lbl1" runat="server" Text='<%# Eval("Grade") %>'></asp:Label>
</ItemTemplate>
<ItemStyle HorizontalAlign="Center" Width="25px" />
</asp:TemplateField>
</Columns>
<HeaderStyle Font-Bold="True" HorizontalAlign="Center" Height="40px"/>
<PagerStyle ForeColor="#8C4510" HorizontalAlign="Center" />
<FooterStyle HorizontalAlign="Center" />
</asp:GridView>
And the back code
Protected void LoadgvResult1()
{
SqlCommand cmdgvKep1 = new SqlCommand();
cmdgvKep1.Connection = conn;
cmdgvKep1.CommandType = CommandType.Text;
cmdgvKep1.CommandText = " SELECT ROW_NUMBER() OVER(ORDER BY Grade ASC) AS Numb, Subjects, Grade ";
cmdgvKep1.CommandText += " FROM Result_SMU ";
cmdgvKep1.CommandText += " WHERE siri = '" + siri + "' ";
conn.Open();
SqlDataAdapter adaptergvKep1 = new SqlDataAdapter(cmdgvKep1);
DataSet dsgvKep1 = new DataSet();
adaptergvKep1.Fill(dsgvKep1, "Result_SMU");
GridViewResult1.DataSource = dsgvKep1;
GridViewResult1.DataBind();
conn.Close();
}

There was a lot of problems with your code.
1)Your data access layer should not be on the same place when you are
DataBind the Grid
2)You should not use global SqlConnection. Connection pool is your
friend. Also if exception occurs your connection will never be closed.
3)Your query should use sql parameters to prevent from Sql Injection.
4) You should wrap SqlDataAdapter in using statement, so it will be disposed
after Fill.
If I understood you correctly you want to fill the grid with dummy records for some reason in the C# when the number of the records are under 15, you can add dummy rows to the fetch dataset like this.
int countRows = dsgvKep1 .Tables[0].Rows.Count;
int dummyRecords = 0;
if(countRows < 15)
{
dummyRecords = 15 - countRows;
}
for (int i = 0; i < dummyRecords; i++)
{
DataTable tbl = dsgvKep1.Tables[0];
DataRow row = tbl.NewRow();
//add dummy values if you want
//row["ColumnName"] = value;
tbl.Rows.Add(row);
}
I advise you to fix the 4 pointers which I gave you. From what I see you are intern and this will be good for you in long term.
I wrote how to create a simple data access layer in this question: checking user name or user email already exists , here you can see data layer, disposing sqlDataAdapter, preventing of not close sql connection when exception occur and also preventing sql injection using SqlComand.Parameters.

Related

Add new data to gridview without refreshing entire gridview

I know the title might make my question look like a duplicate so please read the complete question first.
I have 3 dropdowns in my webform and based on those parameters the data is retrieved from the database and my gridview is populated. What I need is that once a result is displayed, if the user changes the parameters, the new retrieved data should be displayed below the old data. But currently my gridview is refreshing entirely and only the data based on new parameters is displayed.
I have read that one way is to use viewstate but I dont understand what it is. Can someone please help? Thank you.
Ok, so this is a difficult question. It is rather easy to filter, and have a cumulative filter.
So, say we have this screen:
And lots more rows.
So, I can say lets filter by a city.
So this:
Note how we do allow multiple city in the multi-select drop down.
So, I now have this:
Now, lets select those ONLY with a description.
So this:
And then say only active ones. So, this:
So, above is quite easy to setup. Note how any option NOT selected is left out of the critera.
but, a BIG problem exists in the above.
What happens if I want Active from say B.C. but NOT active from Alberta???
I can't do that, and hence your problem.
What we could do however is add a button to above to SAVE the resulting filter, and put the "list" of filters say into a list box or collection.
we then have a search button to search on our collection of filters.
Let me see if this can work - I'll add to above a "box" or collection of each filter.
I would think a union query with distinct row for each filter would do the trick.
So, above example is not too hard - a "cumulative" filter. In fact, the code patter for 2 or 15 filters is quite easy to do here.
However, adding up separate filter requests and combine them? That is somewhat difficult to do.
Edit: Multiple filters
so, while in above, I could say filter by city and get all active, but THEN I want to filter by another city, and get all NON active!!!
That's the problem here.
So, we would have to add code to SAVE the filter. And the HUGE problem with that is how then do we save each filter to "add up" each filter set we want?
We could try and save the raw SQL, but such SQL would be subject to sql injection, and we want to always use parameters.
So, we can and could adopt a design in which we SAVE the resulting SqlCommand object. And then merge the results.
So, now our UI becomes like this:
Lets grab and filter all those from city Edmonton, but Active,
so, this:
We now hit save filter and this:
And now we filter by say City = Banff, but don't care about active or not.
So we have this:
We then save that filter - and now we have this:
I now hit the filter button below the list of filters, and we get this:
So, how does this code work?
Well, I simple saved the Sqlcommand object to a collection (list), and thus combine the results.
So, first our markup at the top for the filter stuff.
<h4>Filters</h4>
<div style="float:left">
<asp:Label ID="Label1" runat="server" Text="Search Hotel"></asp:Label>
<br />
<asp:TextBox ID="txtHotel" runat="server"></asp:TextBox>
</div>
<div style="float:left;margin-left:20px">
<asp:Label ID="Label2" runat="server" Text="Search City"></asp:Label>
<br />
<asp:TextBox ID="txtCity" runat="server"></asp:TextBox>
</div>
<div style="float:left;margin-left:20px">
<asp:Label ID="Label3" runat="server" Text="Must Have Description"></asp:Label>
<br />
<asp:CheckBox ID="chkDescripiton" runat="server" />
</div>
<div style="float:left;margin-left:20px">
<asp:Label ID="Label4" runat="server" Text="Show only Active Hotels"></asp:Label>
<br />
<asp:CheckBox ID="chkActiveOnly" runat="server" />
</div>
<div style="float:left;margin-left:20px">
<asp:Button ID="cmdSearch" runat="server" Text="Search" CssClass="btn" OnClick="cmdSearch_Click"/>
</div>
<div style="float:left;margin-left:20px">
<asp:Button ID="cmdClear" runat="server" Text="Clear Fitler" CssClass="btn" OnClick="cmdClear_Click"/>
</div>
<div style="float:left;margin-left:20px">
<asp:Button ID="cmdTest" runat="server" Text="Save Filter"
CssClass="btn" OnClick="cmdTest_Click"
OnClientClick="return myfilterprompt()"
/>
<asp:HiddenField ID="HFilterName" runat="server" ClientIDMode="Static"/>
<script>
function myfilterprompt() {
sFilter = ""
sFilter = prompt('Enter name for filter ')
if ( (sFilter === null) || (sFilter === "") ){
return false
}
$('#HFilterName').val(sFilter)
return true
}
</script>
</div>
<div style="float:left;margin-left:30px;width:190px">
<asp:ListBox ID="lstFilters" runat="server" Width="100%" Height="100px"
DataTextField="sFilterName" >
</asp:ListBox>
<asp:Button ID="cmdMultiFilter" runat="server" Text="Filter"
CssClass="btn" OnClick="cmdMultiFilter_Click" style="float:left" />
<asp:Button ID="cmdMultiClear" runat="server" Text="Clear"
CssClass="btn" OnClick="cmdMultiClear_Click" style="float:right"/>
</div>
then below above is our grid:
<asp:GridView ID="GridView1" runat="server"
AutoGenerateColumns="False" DataKeyNames="ID"
CssClass="table" Width="60%" ShowHeaderWhenEmpty="true">
<Columns>
<asp:BoundField DataField="FirstName" HeaderText="FirstName" />
<asp:BoundField DataField="LastName" HeaderText="LastName" />
<asp:BoundField DataField="HotelName" HeaderText="HotelName" />
<asp:BoundField DataField="City" HeaderText="City" />
<asp:BoundField DataField="Province" HeaderText="Province" />
<asp:BoundField DataField="Description" HeaderText="Description" />
<asp:BoundField DataField="Active" HeaderText="Active" />
</Columns>
</asp:GridView>
So, code to load:
List<MyFilter> MyFilters = new List<MyFilter>();
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack == false)
{
SqlCommand cmdSQL = new
SqlCommand("SELECT * FROM tblHotels WHERE ID = 0");
LoadGrid(cmdSQL);
Session["MyFilters"] = MyFilters;
}
else
MyFilters = (List<MyFilter>)Session["MyFilters"];
}
public void LoadGrid(SqlCommand cmdSQL)
{
DataTable rstData = MyRstP(cmdSQL);
GridView1.DataSource = rstData;
GridView1.DataBind();
}
And now our search button:
protected void cmdSearch_Click(object sender, EventArgs e)
{
SqlCommand cmdSQL = GetMyCommand();
LoadGrid(cmdSQL);
}
SqlCommand GetMyCommand()
{
string strSQL = "SELECT * FROM tblHotels ";
string strORDER = " ORDER BY HotelName";
string strFilter = "";
SqlCommand cmdSQL = new SqlCommand();
if (txtHotel.Text != "")
{
strFilter = "(HotelName like #HotelName + '%')";
cmdSQL.Parameters.Add("#HotelName", SqlDbType.NVarChar).Value = txtHotel.Text;
}
if (txtCity.Text != "")
{
if (strFilter != "") strFilter += " AND ";
strFilter += "(City Like #City + '%') ";
cmdSQL.Parameters.Add("#City", SqlDbType.NVarChar).Value = txtCity.Text;
}
if (chkActiveOnly.Checked)
{
if (strFilter != "") strFilter += " AND ";
strFilter += "(Active = 1)";
}
if (chkDescripiton.Checked)
{
if (strFilter != "") strFilter += " AND ";
strFilter += "(Description is not null)";
}
if (strFilter != "") strSQL += " WHERE " + strFilter;
strSQL += strORDER;
cmdSQL.CommandText = strSQL;
return cmdSQL;
}
And now our save the filter button code:
protected void cmdTest_Click(object sender, EventArgs e)
{
MyFilter OneFilter = new MyFilter();
OneFilter.sFilterName = HFilterName.Value;
OneFilter.cmdSQL = GetMyCommand();
MyFilters.Add(OneFilter);
lstFilters.DataSource = MyFilters;
lstFilters.DataBind();
}
public class MyFilter
{
public string sFilterName { get; set; }
public SqlCommand cmdSQL = new SqlCommand();
}
And our multi-filter code button.
Now, for large data sets - not a great idea, but a start:
protected void cmdMultiFilter_Click(object sender, EventArgs e)
{
List<DataTable> MyTables = new List<DataTable>();
foreach (MyFilter OneFilter in MyFilters)
{
DataTable rstDT = MyRstP(OneFilter.cmdSQL);
MyTables.Add(rstDT);
}
DataTable rstData = MyTables[0];
for (int i = 1;i < MyTables.Count;i++)
{
rstData.Merge(MyTables[i]);
}
GridView1.DataSource = rstData;
GridView1.DataBind();
}
so, you can build list up of "filters" and display them in a listbox and then have a filter button that merges all of the filtering.
And one more helper routine I used:
public DataTable MyRstP(SqlCommand cmdSQL)
{
DataTable rstData = new DataTable();
using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
{
using (cmdSQL)
{
cmdSQL.Connection = conn;
conn.Open();
rstData.Load(cmdSQL.ExecuteReader());
}
}
return rstData;
}
These systems can be really nice. Often a group of managers will say, lets grab all customers from west coast. Yuk - too many. Ok, only those with purchases in last 2 months - ah, that's nice.
then they say, lets get all customers who never purchased anything, but from the south - and add those to the list - but only active on our mailing list.
So, this type of slice and dice - get some of those, and then get some of these, and then combine them?
This type of business query system and being able to combine these, and those, and them, and then toss in a few more? Often they will keep going say until such time they get say 10,000 results (which happens to be how many catalogs they have left they would like to send out).
So, I solved my problem by using a little outside the box thinking. I am posting it here for anyone visiting this question or having a same problem in the future could see this:
So what I did is that I extracted the data from the database based on the parameters selected by the user from the dropdowns. In the database, I had created a temp table to store the extracted temporarily. So I inserted the data into that temporary table and used that table to populate the gridview. I had to add a reset button, when the user clicked it the all the data is deleted from the temp table and also the page reset to its default with gridview not visible and dropdowns having no selection.

Access HyperLink inside ItemTemplate inside TemplateField ASP.Net WebForms

I have an ASP TemplateField inside a data populated GridView as follows:
<asp:GridView ID="gvReport" runat="server" AutoGenerateColumns="False" ShowHeaderWhenEmpty="true" OnRowDataBound="gvReport_RowDataBound" CssClass="table table-bordered">
<Columns>
<asp:BoundField DataField="Delete" HeaderText="Delete" SortExpression="Delete" />
<asp:TemplateField HeaderText="Delete">
<ItemTemplate>
<asp:HyperLink runat="server" NavigateUrl='<%# "Edit?from=Delete&ID=" + Eval("ID") %>' ImageUrl="Assets/SmallDelete.png" SortExpression="PathToFile" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
In other words, at the end of each row, there is a delete 'button'. I can tell whether a particular row/record has been deleted by checking the true/false value of the BoundField Delete in my code behind as follows:
if (e.Row.RowType == DataControlRowType.DataRow)
{
TableCell statusCell = e.Row.Cells[0];
if (statusCell.Text == "True")
{
//change ImageUrl of Hyperlink for this row
}
}
Right now, my icon is red for delete, but in the case that a record has already been deleted,
I would like to change the image to a different icon (a blue one).
How can I change this ImageUrl if statusCell evaluates to true?
ok, so we will need two parts here:
We need (want) to persist the data table that drives the grid).
The REASON for this?
We kill about 3 birds with one stone.
We use the data table store/save/know the deleted state
We use that delete information to toggle our image
(and thus don't have to store the state in the grid view).
We ALSO then case use that table state to update the database in ONE shot, and thus don't have to code out a bunch of database operations (delete rows). We just send the table back to the database.
In fact in this example, I can add about 7 lines of code, and if you tab around, edit the data? It ALSO will be sent back to the database. And this means no messy edit templates and all that jazz (which is panful anyway).
Ok, so, here is our grid - just some hotels - and our delete button with image:
markup:
<div style="width:40%;margin-left:20px">
<asp:GridView ID="GridView1" runat="server"
AutoGenerateColumns="False"
DataKeyNames="ID" CssClass="table table-hover borderhide" >
<Columns>
<asp:TemplateField HeaderText="HotelName" >
<ItemTemplate><asp:TextBox id="HotelName" runat="server" Text='<%# Eval("HotelName") %>' /></ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="FirstName" SortExpression="ORDER BY FirstName" >
<ItemTemplate><asp:TextBox id="FirstName" runat="server" Text='<%# Eval("FirstName") %>' /></ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="LastName" >
<ItemTemplate><asp:TextBox id="LastName" runat="server" Text='<%# Eval("LastName") %>' /></ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="City" >
<ItemTemplate><asp:TextBox id="City" runat="server" Text='<%# Eval("City") %>' /></ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Delete">
<ItemTemplate>
<asp:ImageButton ID="cmdDelete" runat="server" Height="20px" Style="margin-left:10px"
ImageUrl="~/Content/cknosel.png"
Width="24px" OnClick="cmdDelete_Click"></asp:ImageButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<br />
<asp:Button ID="cmdDeleteAll" runat="server" Text="Delete selected" Width="122px"
OnClientClick="return confirm('Delete all selected?')" />
</div>
Ok, and the code to load up the grid - NOTE WE persist the data table!!!!!
Code:
DataTable rstTable = new DataTable();
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
LoadGrid();
else
rstTable = (DataTable)ViewState["rstTable"];
}
void LoadGrid()
{
// load up our grid
using (SqlCommand cmdSQL = new SqlCommand("SELECT * from tblHotels ORDER BY HotelName ",
new SqlConnection(Properties.Settings.Default.TEST4)))
{
cmdSQL.Connection.Open();
rstTable.Clear();
rstTable.Load(cmdSQL.ExecuteReader());
GridView1.DataSource = rstTable;
GridView1.DataBind();
}
ViewState["rstTable"] = rstTable;
}
Ok, so far, real plain jane. The result is this:
Ok, so now all we need is to add the delete button click event.
That code looks like this:
protected void cmdDelete_Click(object sender, ImageClickEventArgs e)
{
ImageButton btn = (ImageButton)sender;
GridViewRow rRow = (GridViewRow)btn.Parent.Parent;
DataRow OneRow = rstTable.Rows[rRow.DataItemIndex];
// toggle data
if (OneRow.RowState == DataRowState.Deleted)
{
// undelete
OneRow.RejectChanges();
btn.ImageUrl = "/Content/cknosel.png";
}
else
{
// delete
OneRow.Delete();
btn.ImageUrl = "/Content/ckdelete.png";
}
}
Again, really simple. But NOTE how we use the data table row state (deleted or not).
And this ALSO toggles the image for the delete button.
So, we don't have to care, worry, or store/save the sate in the grid.
So, if I click on a few rows to delete, I now get this:
So far - very little code!!!
Ok, so now the last part. the overall delete selected button. Well, since that is dangerous - note how I tossed in a OnClientClick event to "confirm the delete. if you hit cancel, then of course the server side event does not run.
But, as noted since we persisted the table? Then we can send the table deletes right back to the server without a loop. The delete code thus looks like this:
protected void cmdDeleteAll_Click(object sender, EventArgs e)
{
// send updates (deletes) back to database.
using (SqlCommand cmdSQL = new SqlCommand("SELECT * from tblHotels WHERE ID = 0",
new SqlConnection(Properties.Settings.Default.TEST4)))
{
cmdSQL.Connection.Open();
SqlDataAdapter daUpdate = new SqlDataAdapter(cmdSQL);
SqlCommandBuilder daUpdateBuild = new SqlCommandBuilder(daUpdate);
daUpdate.Update(rstTable);
}
LoadGrid(); // refesh display
}
So, note how easy it is to update (delete) from the database. If you look close, I used text boxes for that grid - not labels. The reason of course is that if the user tabs around in the grid (and edits - very much like excel), then I can with a few extra lines of code send those changes back to the database. In fact the above delete button code will be 100% identical here (it will send table changes back with the above code. So, if we add rows, edit rows then the above is NOT really a delete command, but is in fact our save edits/deletes/adds command!

delete row from gridview sql

I want to be able to delete a row when I click on the delete button on that gridview. I have the aspx page and the code behind as well as the app code. The DeletePaymentCondition runs the store procedure to delete the row. But somehow the overall code doesnt work
aspx
<asp:GridView ID="gridview1" runat="server" HorizontalAlign="left" AutoGenerateColumns="false" CssClass="table table-bordered " GridLines="None"
AllowSorting="True" OnRowDeleting="OnRowDeleting">
<Columns>
<asp:TemplateField ItemStyle-HorizontalAlign="left" HeaderText="Payment Condition" HeaderStyle-CssClass="OGColor" HeaderStyle-ForeColor="white" SortExpression="monthToQuarters">
<ItemTemplate>
<span style="font-size:12px; color: #2980b9; text-align:left">
<asp:Label ID="lblUserId" runat="server" Visible="true" Text="<%# bind('payConditionId')%>"/>
</span>
</ItemTemplate>
</asp:TemplateField>
<asp:CommandField ButtonType="Link" ShowEditButton="true" ShowDeleteButton="true" ItemStyle-Width="150"/>
</Columns>
</asp:GridView>
cs
protected void OnRowDeleting(object sender, GridViewDeleteEventArgs e)
{
Label lblEmpID = (Label)gridPayment.Rows[e.RowIndex].FindControl("lblUserId"); //This is Table Id load on Label1
int id = Convert.ToInt32(lblEmpID.Text.ToString());
dsPayment = objcommission.Delete(id);
gridPayment.DataSource = dsPayment.Tables[0];
gridPayment.DataBind();
}
app code
public DataSet DeletePayment(int id)
{
DataSet dsGetAllPayment;
dsGetAllPaymentCondition = SqlHelper.ExecuteDataset(OGconnection, CommandType.Text, "Delete FROM tblPay where pay ='" + id + "'");
return dsGetAllPayment;
}
You shoul execute two different SQL, one for the delete and a new select one to retreive the new data.
The DELETE should be executed using in a NonQuery because it does not return rows (only the number of rows affected).
public DataSet DeletePaymentCondition(int ids)
{
int rowsAffected = SqlHelper.ExecuteNonQuery(OGconnection, CommandType.Text, "Delete FROM [Accounting].[dbo].[tblPayConditions] where payConditionId ='" + ids + "'");
DataSet dsGetAllPaymentCondition = SqlHelper.ExecuteDataSet(OGconnection, CommandType.Text, "Select * FROM [Accounting].[dbo].[tblPayConditions]");
return dsGetAllPaymentCondition;
}
As a good praxys, you should consider changing it into parametrized queries. In this case it is safe because of the integer conversion, but in similar code with string parameters you would be prone to SQL Injection attacks
I got the solution. I've made changes to the cs file and as well as the code provided by bradbury9.
protected void OnRowDeleting(object sender, GridViewDeleteEventArgs e)
{
int index = Convert.ToInt32(gridPaymentCondition.DataKeys[e.RowIndex].Value.ToString());
dsPaymentCondition = objcommission.DeletePaymentCondition(index);
gridPaymentCondition.DataSource = dsPaymentCondition.Tables[0];
updatePaymentConditionsWithoutRefresh();
}

Checking Username Available Doesn't Work

I have an asp.net web forms application which when a user tabs out of the username field it checks my database to see if its available or not but the issue I am having is that it always seems to fall into the exists even if it doesn't.
I have watched many videos on it and also read many articles but I can't get it to work at all.
I have provided all my code below.
Config
<add name="PaydayLunchConnectionString1" connectionString="Data Source=********\*******;Initial Catalog=************;Integrated Security=True"
providerName="System.Data.SqlClient" />
HTML
<asp:GridView ID="tblUsers" runat="server" AutoGenerateColumns="False" CellPadding="4" DataSourceID="SqlUsers" GridLines="None" Width="15%">
<AlternatingRowStyle BackColor="White" />
<Columns>
<asp:BoundField DataField="Name" HeaderText="Name" SortExpression="Name" />
</Columns>
<HeaderStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
<RowStyle BackColor="#EFF3FB" />
</asp:GridView>
<asp:SqlDataSource ID="SqlUsers" runat="server" ConnectionString="<%$ ConnectionStrings:PaydayLunchConnectionString1 %>" SelectCommand="SELECT [Name] FROM [Users] WHERE [name] != 'Admin'"></asp:SqlDataSource>
<asp:Label ID="removeUserNotExist" runat="server" Text="The user entered does not exist. Please try again." Visible="false" style="color: red"></asp:Label>
<asp:Label ID="removeUserExists" runat="server" Text="The user entered exists." Visible="false" style="color: green"></asp:Label>
<div class="form-group">
<asp:Label runat="server" AssociatedControlID="txtRemoveUser" CssClass="col-sm-offset-2 col-sm-3 control-label">Enter Name To Be Removed</asp:Label>
<div class="col-sm-3">
<asp:TextBox runat="server" ID="txtRemoveUser" CssClass="form-control" AutoPostBack="true" OnTextChanged="txtRemoveUser_TextChanged" />
</div>
</div>
Code Behind
using System.Data.SqlClient;
using System.Configuration;
using System.Data;
protected void txtRemoveUser_TextChanged(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(txtRemoveUser.Text))
{
string connection = ConfigurationManager.ConnectionStrings["PaydayLunchConnectionString1"].ConnectionString;
SqlConnection conn = new SqlConnection(connection);
conn.Open();
SqlCommand cmd = new SqlCommand("SELECT * FROM Users WHERE Name != #Name", conn);
cmd.Parameters.AddWithValue("#Name", txtRemoveUser.Text);
SqlDataReader rd = cmd.ExecuteReader();
if (rd.HasRows)
{
removeUserNotExist.Visible = true;
removeUserExists.Visible = false;
}
else
{
removeUserNotExist.Visible = false;
removeUserExists.Visible = true;
}
}
}
DB Details
Table Name = Users
Columns = ID, Name, Password
Users = Test, Test2
If I enter 'Test' in the field and tab out, I get the correct message (Exists) but if i then enter 'ABC' I still get the 'Exists' message.
If there is more than 1 user in your database, this query will always produce rows. Hence, your if statement always produces the same result:
SELECT * FROM Users WHERE Name != #Name
If you want to check if a user name exists, simply check for equality.
SELECT * FROM Users WHERE Name = #Name
If that one returns a row, the user name exists. Otherwise it doesn't.
A better solution would be to use 1 in the select, since that prevents the database to return all row data, a small performance improvement:
SELECT 1 dummy FROM Users WHERE Name = #Name

SQL Server / C# : Filter for System.Date - results only entries at 00:00:00

I have a connected SQL Server database in Visual Studio and am displaying its content in a grid. I created a dropdown menu with the column names as selectable options and a text field to filter for specific content, e.g., DropDown = "Start" - Textfield = 14.03.2015 = Filter Column "Start" for each entry that contains "14.03.2015" - and display it in the Grid.
I'm basically done with that part. The only problem left that I'm facing is whenever I enter a date - e.g., 14.03.2015 it only displays dates which start at 00:00:00 - the other entries that do not start at 00:00:00 are ignored and I can't figure out how to modify this to work properly.
The Grid looks like this: http://abload.de/img/untitled123yqkyn.png
And I am using the following C# code to filter:
protected void Button1_Click(object sender, EventArgs e)
{
string FilterExpression = string.Empty;
if (DropDownList1.SelectedValue.ToString().Equals("Start"))
{
FilterExpression = string.Format("Start = '{0}'", TextBox1.Text);
}
else if (DropDownList1.SelectedValue.ToString().Equals("End"))
{
FilterExpression = string.Format("End = '{0}'", TextBox1.Text);
}
else if (DropDownList1.SelectedValue.ToString().Equals("Creation Time"))
{
FilterExpression = string.Format("DateTimeCreated = '{0}'", TextBox1.Text);
}
else if (DropDownList1.SelectedValue.ToString().Equals("Last Modified"))
{
FilterExpression = string.Format("LastModifiedTime = '{0}'", TextBox1.Text);
}
else
{
FilterExpression = string.Concat(DropDownList1.SelectedValue, " Like '%{0}%'");
}
SqlDataSource1.FilterParameters.Clear();
SqlDataSource1.FilterParameters.Add(new ControlParameter(DropDownList1.SelectedValue, "TextBox1", "Text"));
SqlDataSource1.FilterExpression = FilterExpression;
}
This is my Grid:
Organizer
Room
Creation Time
Start
End
Last Modified
<asp:TextBox ID="TextBox1" runat="server" Width="315px"></asp:TextBox>
<asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Search" Width="100px"/>
<asp:Button ID="Button2" runat="server" OnClick="Button2_Click" Text="Reset Search" Width="100px"/>
<br/>
<br/>
<asp:GridView ID="GridView1" runat="server" BorderColor="#F9F9F9" BorderStyle="Solid" CellPadding="4" ForeColor="#333333" AutoGenerateColumns="False" DataKeyNames="ID" DataSourceID="SqlDataSource1" AllowSorting="True" pagesize="1000" AllowPaging="True" HorizontalAlign="Center">
<AlternatingRowStyle BackColor="White"/>
<Columns>
<asp:BoundField DataField="ID" HeaderText="ID" InsertVisible="False" ReadOnly="True" SortExpression="ID" ItemStyle-HorizontalAlign="Center"/>
<asp:BoundField DataField="Organizer" HeaderText="Organizer" SortExpression="Organizer" ConvertEmptyStringToNull="False" HtmlEncode="False" HtmlEncodeFormatString="False" InsertVisible="False"/>
<asp:BoundField DataField="Room" HeaderText="Room" SortExpression="Room"/>
<asp:BoundField DataField="DateTimeCreated" HeaderText="Creation Time" SortExpression="DateTimeCreated"/>
<asp:BoundField DataField="Start" HeaderText="Start" SortExpression="Start" />
<asp:BoundField DataField="End" HeaderText="End" SortExpression="End"/>
<asp:BoundField DataField="LastModifiedTime" HeaderText="Last Modified" SortExpression="LastModifiedTime" />
<asp:CheckBoxField DataField="Cancelled" HeaderText="Cancelled" SortExpression="Cancelled" ItemStyle-HorizontalAlign="Center" />
</Columns>
<EditRowStyle BackColor="#2461BF"/>
<FooterStyle BackColor="#E1000F" Font-Bold="True" ForeColor="White"/>
<HeaderStyle BackColor="#E1000F" Font-Bold="True" ForeColor="White" Font-Underline="false"/>
<PagerStyle BackColor="#E1000F" ForeColor="White" HorizontalAlign="Center"/>
<RowStyle BackColor="#F9F9F9"/>
<SelectedRowStyle BackColor="#D1DDF1" Font-Bold="True" ForeColor="#333333"/>
</asp:GridView>
<asp:SqlDataSource ID="xyz" runat="server" ConnectionString="<%$ ConnectionStrings:VCConnectionString %>" SelectCommand="SELECT * FROM [xyz]"></asp:SqlDataSource>
</center>
Please excuse the quality of the code, I'm completely new to C# and for that matter programming in itself. I hope that there is someone able to help me.
What happens if you change all of the filters to use 'LIKE':
if (DropDownList1.SelectedValue.ToString().Equals("Start"))
{
FilterExpression = string.Format("Start LIKE '{0}%'", TextBox1.Text);
}
Then, you're not matching against an exact date (at midnight), but matching any date-times which start with that date.
Update
Or perhaps you could try this...
if (DropDownList1.SelectedValue.ToString().Equals("Start"))
{
FilterExpression = string.Format("Start >= '{0} 0:00:00' AND Start <= '{1} 23:59:59'", TextBox1.Text, TextBox1.Text);
}
Update 2
... Or if you really want to make sure you get all records from that final second of 23:59:59, you could use this (I think)...
if (DropDownList1.SelectedValue.ToString().Equals("Start"))
{
FilterExpression = string.Format("Start >= '{0} 0:00:00' AND Start < DATEADD(day,1,'{1}')", TextBox1.Text, TextBox1.Text);
}
Notice that the version looks for records less than your given date "plus one day".
Personally, I would use the "Update 1" script, and compare the dates against 23:59:59, even though, yes, it would ignore records created in that final second of the day (eg at 23:59:59.403).
The problem is due to the fact you're filtering on a datetime value; if you set only the date part the system interprets it as at midnight. Try to pass also the time value and it will work.
EDIT:
The problem is due the conversion from string and datetime:
else
{
FilterExpression = string.Concat(DropDownList1.SelectedValue, " Like '%{0}%'");
}
Perhaps changing your logic to use the value as a dateime should work.
In the folowing example the first doesn't work, the second one does:
SELECT *
FROM [Events]
WHERE EventDate LIKE '%2012-06-08%'
SELECT *
FROM [Events]
WHERE EventDate >= '2012-06-08' AND EventDate <= '2012-06-08 23:59:59'

Categories