I have a page that executes a custom query that its saved somewhere on the database.
I need to be able to enable pagination on the gridview.
For example purposes the query saved on the database its like this:
select * from requestbases
This returns 10,000 rows.
With the method below I make it return 10 rows.
public DataTable GetGenericResults(string strsql, int pageIndex)
{
StringBuilder sb = new StringBuilder();
sb.Append("WITH MyPagedData as ( ");
int indexFrom = strsql.IndexOf("from");
sb.Append(strsql.Substring(0, indexFrom));
sb.Append(", ");
sb.Append("ROW_NUMBER() OVER(ORDER BY RequestBaseId DESC) as RowNum ");
sb.Append(strsql.Substring(indexFrom));
sb.Append(") ");
sb.Append("SELECT * from MyPagedData where RowNum between #StartIndex and #StartIndex + 10");
using(var connection = (SqlConnection)_context.Database.Connection)
{
var adapter = new SqlDataAdapter(sb.ToString(), connection);
adapter.SelectCommand.Parameters.Add("#StartIndex", SqlDbType.Int).Value = pageIndex;
var results = new DataSet();
adapter.Fill(results, "Results");
return results.Tables["Results"];
}
}
And this is the code to bind the grid
var datatable = RequestBaseBL.GetGenericResults(query.QuerySql, 0);
if (datatable.Rows.Count > 0)
{
LblCount.Text = datatable.Rows.Count + " records";
PanelResults.Visible = true;
GrvCustomResults.Visible = true;
GrvCustomResults.DataSource = datatable;
GrvCustomResults.DataBind();
}
The problem is that the query itself returns 10 rows, so the gridview will never show a pager.
<asp:GridView ID="GrvCustomResults" runat="server" Visible="false" AutoGenerateColumns="true">
<PagerSettings
Visible="true"
Position="TopAndBottom"
PreviousPageText="Previous"
NextPageText="Next"
Mode="NumericFirstLast" />
<HeaderStyle CssClass="gridheader" />
this code in aspx page
<asp:Panel runat="server" id="pnlPager" CssClass="pager">
</asp:Panel>
Here the method that will use in the .cs page
This is used to track the record of the pagenum and pagesize
protected int PageNum
{
get { return Convert.ToInt16(ViewState["PageNum"]); }
set { ViewState["PageNum"] = value; }
}
protected int PageSize
{
get { return Convert.ToInt16(ViewState["PageSize"]); }
set { ViewState["PageSize"] = value; }
}
protected int TotalRecord
{
get { return Convert.ToInt16(ViewState["TotalRecords"]); }
set { ViewState["TotalRecords"] = value; }
}
This is the method is used for the call the store procedure that will send the pagenum ,page size
public DataSet GetCollegeSerachData(int PageNum,int PageSize,out int TotalRecords)
{
DS = new DataSet();
ObjDataWrapper = new DataWrapper(ClsCommon.CnnString, CommandType.StoredProcedure);
TotalRecords=0;
ErrorCount = 0;
Searchpattern = "";
try
{
ObjDataWrapper.AddParameter("#PageNum", PageNum);
ObjDataWrapper.AddParameter("#PageSize", PageSize);
SqlParameter ObjTotalRecords=(SqlParameter)(ObjDataWrapper.AddParameter("#TotalRowsNum","",SqlDbType.Int,ParameterDirection.Output));
DS=ObjDataWrapper.ExecuteDataSet("ADMJGetCollegeSearch");
if(ObjTotalRecords.Value!= DBNull.Value || ObjTotalRecords!=null)
{
TotalRecords=Convert.ToInt32(ObjTotalRecords.Value);
}
}
catch (Exception Ex)
{
string err = Ex.Message;
if (Ex.InnerException != null)
{
err = err + " :: Inner Exception :- " + Ex.InnerException.Message;
}
string addInfo = "Error While Executing GetCollegeSerachData in ClsColleges:: -> ";
ClsExceptionPublisher objPub = new ClsExceptionPublisher();
objPub.Publish(err, addInfo);
}
return DS;
}
that will return the dataset that will used to bind the store procedure
here the store procedure that will used for pagination
GO
/****** Object: StoredProcedure [dbo].[ADMJGetCollegeSearch] Script Date: 06/06/2012 15:43:29 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[ADMJGetCollegeListByState]
#PageNum int,
#PageSize int,
#TotalRowsNum int output
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
WITH College_CollegeId As
(
SELECT 'RowNumber' = ROW_NUMBER() OVER(ORDER BY collegeid asc),College.*
FROM College
)
-- Query result
SELECT *
FROM College_CollegeId
WHERE RowNumber BETWEEN (#PageNum - 1) * #PageSize + 1 AND #PageNum * #PageSize
ORDER BY collegename asc
-- Returns total records number
SELECT #TotalRowsNum = count(*)
FROM College
END
at last you will bind the the gridview
grdCourse.DataSource = DS.Tables[0];
grdCourse.DataBind();
grdCourse.Visible = true;
at the PageIndexChanging(object sender, GridViewPageEventArgs e) of the grid view you will pass the
protected void grdCourse_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
Pagenum = e.NewPageIndex;
--call this method public DataSet GetCollegeSerachData(int PageNum,int PageSize,out int TotalRecords)
}
Related
I need some help on how to achieved Inserting a foreign key value in MS SQL at the same time binding the result in gridview in the same aspx page.
I have my code which is works fine and no error upon Build Solution but it shows the following line error in the browser.
Line: 940 Error: Sys.WebForms.PageRequestManagerServerErrorException:
A field or property with the name 'TypeName' was not found on the
selected data source.
I'm using MS SQL 2008 & MS Visual Studio 2013
Below is my code in my project
ASPX Gridview:
<!-- Main Gridview -->
<asp:GridView ID="gvItemgrid" runat="server" AutoGenerateColumns="false" DataKeyNames="ItemID"
ShowHeader="false" CssClass="Grid">
<RowStyle Wrap="false" CssClass="row" />
<AlternatingRowStyle BackColor="White" />
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:ImageButton ID="imgbtn" ImageUrl="../images/Edit.jpg" runat="server" Width="12px" Height="12px" OnClick="imgbtn_Click" /></ItemTemplate>
</asp:TemplateField>
<asp:BoundField ItemStyle-Width="50px" DataField="ItemID" HeaderText="ItemID" />
<asp:BoundField ItemStyle-Width="500px" DataField="ItemName" HeaderText="ItemName" />
<asp:BoundField ItemStyle-Width="500px" DataField="TypeName" HeaderText="TypeName" />
</Columns>
</asp:GridView>
C# Code:
// C# Code
#region BindTypeList (ddlType)
// bind the Type list in drop down list..
private void BindTypeList(DropDownList ddlType)
{
SqlConnection con = new SqlConnection(strConnString);
SqlDataAdapter sda = new SqlDataAdapter();
SqlCommand cmd = new SqlCommand("select * from inv_TypeList");
cmd.Connection = con;
con.Open();
this.ddlType.DataSource = cmd.ExecuteReader();
this.ddlType.DataTextField = "TypeName";
this.ddlType.DataValueField = "TypeID";
this.ddlType.DataBind();
con.Close();
}
#endregion
//button save
#region btnSave
protected void btnSave_Click(object sender, EventArgs e)
{
//Calling the database for Insert Statement
SqlConnection con = new SqlConnection(strConnString);
// call stored procedure
SqlCommand cmd = new SqlCommand("inv_ItemList_Insert", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Connection = con;
// add values
cmd.Parameters.AddWithValue("#ItemName", txtItemName.Text);
cmd.Parameters["#ItemName"].Value = txtItemName.Text;
cmd.Parameters.AddWithValue("#TypeID", ddlType.SelectedItem.Value);
cmd.Parameters["#TypeID"].Value = ddlType.SelectedItem.Value;
// add the result
cmd.Parameters.Add(new SqlParameter("#Result", SqlDbType.VarChar, 1000));
cmd.Parameters["#Result"].Direction = ParameterDirection.Output;
try
{
// open the database..
con.Open();
cmd.ExecuteNonQuery();
// perform some actions here..
//btnSave.Enabled = false;
string result = cmd.Parameters["#Result"].Value.ToString();
// label notification..
lblMsg.Visible = false;
lblMsg.Text = result;
BindGrid();
// if meets condition to perform some actions..
if ((lblMsg.Text == ("Item Name: " + (txtItemName.Text + (" " + "already exists..")))))
{
// controls set to active..
txtItemName.Enabled = true;
ddlType.Enabled = true;
//txtRegister.Text = DateTime.Now.ToString("MM/dd/yyyy hh:mm:ss tt");
txtItemName.Focus();
// lblMsg notification display
lblMsg.Attributes.Add("style", "color: #FFFFFF");
lblMsg.Attributes.Add("style", "background-color: OrangeRed");
lblMsg.Visible = false;
btnNew.Enabled = false;
// javascript messagebox "IP Address exist!"
ScriptManager.RegisterStartupScript(UpdatePanel1, UpdatePanel1.GetType(), "msgExist", "msgExist();", true);
}
else
{
//Method in displaying data in reverse (last - first)
//Calling the database
SqlConnection con2 = new SqlConnection(strConnString);
string strConString = "select * from inv_ItemList order by ItemID DESC";
SqlCommand cmd2 = new SqlCommand(strConString);
gvItemgrid.DataSource = GetData(strConString);
gvItemgrid.DataBind();
//Highlighting the first row in gridview
object firstRowIndex = gvItemgrid.Rows[0];
gvItemgrid.Rows[0].BackColor = System.Drawing.Color.LemonChiffon;
//Display records
//current record per page
int val1 = Convert.ToInt32(gvItemgrid.Rows.Count.ToString());
int val2 = Convert.ToInt32(lblcurrentpage.Text.ToString());
int val3 = val1 * val2;
lblrecperpage.Text = Convert.ToString(val3);
//display page
lbltotalpage.Text = lblcurrentpage.Text;
//paging function disabled..
btnFirst.Enabled = false;
btnNext.Enabled = false;
btnPrevious.Enabled = false;
btnLast.Enabled = false;
//controls set to disabled
txtItemName.Enabled = false;
btnSave.Enabled = false;
////current date and time
//txtRegister.Text = DateTime.Now.ToString("MM/dd/yyyy hh:mm:ss tt");
// lblMsg notification display
lblMsg.Attributes.Add("style", "color:#FFFFFF");
lblMsg.Attributes.Add("style", "background-color:Green");
// javascript messagebox "Data successfully saved"
ScriptManager.RegisterStartupScript(UpdatePanel1, UpdatePanel1.GetType(), "msgSave", "msgSave();", true);
}
}
//catching internal error
catch (SqlException ex)
{
// throw some internal error in case there is
string errorMessage = "Error in registring user";
errorMessage = (errorMessage + ex.Message);
throw new Exception(errorMessage);
}
finally
{
//close the database..
con.Close();
}
// button new enabled..
btnNew.Enabled = true;
}
#endregion
// bind grid..
#region BindGrid
private void BindGrid()
{
// Call the Database & Stored Procedure for total Records
SqlConnection myConnection = new SqlConnection(strConnString);
SqlCommand myCommand = new SqlCommand("inv_ItemList_BindGrid", myConnection);
myCommand.CommandType = CommandType.StoredProcedure;
myCommand.Parameters.AddWithValue("#startRowIndex", currentPageNumber);
myCommand.Parameters.AddWithValue("#maximumRows", PAGE_SIZE);
myCommand.Parameters.Add("#totalRows", SqlDbType.Int, 4);
myCommand.Parameters["#totalRows"].Direction = ParameterDirection.Output;
myCommand.Parameters.Add("#totalRec", SqlDbType.Int, 4);
myCommand.Parameters["#totalRec"].Direction = ParameterDirection.Output;
SqlDataAdapter ad = new SqlDataAdapter(myCommand);
DataSet ds = new DataSet();
ad.Fill(ds);
gvItemgrid.DataSource = ds;
gvItemgrid.DataBind();
// Display the total records & pages..
double totalRows = int.Parse(myCommand.Parameters["#totalRows"].Value.ToString());
double totalRec = int.Parse(myCommand.Parameters["#totalRec"].Value.ToString());
lbltotalrec.Text = CalculateTotalRow(totalRec).ToString();
lbltotalpage.Text = CalculateTotalPages(totalRows).ToString();
// current page value
lblcurrentpage.Text = currentPageNumber.ToString();
// conditional meets
if ((currentPageNumber == 1))
{
// button first & prev disabled..
btnFirst.Enabled = false;
btnPrevious.Enabled = false;
if ((Int32.Parse(lbltotalpage.Text.ToString()) > 0))
{
btnNext.Enabled = true;
btnLast.Enabled = true;
}
else
{
btnNext.Enabled = false;
}
}
else
{
btnPrevious.Enabled = true;
btnFirst.Enabled = true;
if ((currentPageNumber == Int32.Parse(lbltotalpage.Text.ToString())))
{
btnNext.Enabled = false;
btnLast.Enabled = false;
}
else
{
btnNext.Enabled = true;
btnLast.Enabled = true;
}
}
//current record per page
int val1 = Convert.ToInt32(gvItemgrid.Rows.Count.ToString());
int val2 = Convert.ToInt32(lblcurrentpage.Text.ToString());
int val3 = val1 * val2;
lblrecperpage.Text = Convert.ToString(val3);
// conditional meets equalize the last page value & records..
if ((btnLast.Enabled == false))
{
lblrecperpage.Text = "";
lblrecperpage.Text = totalRec.ToString();
}
else
{
// point out the record at the end of the page..
lblrecperpage.Text = Convert.ToString(val3);
}
// condition
if ((lblrecperpage.Text == lbltotalrec.Text))
{
btnNext.Enabled = false;
btnLast.Enabled = false;
}
else
{
btnNext.Enabled = true;
btnLast.Enabled = true;
}
}
#endregion
SQL Stored Procedure: inv_ItemList_Insert
ALTER PROCEDURE [dbo].[inv_ItemList_Insert]
-- Add the parameters for the stored procedure here
#ItemName VARCHAR(50),
#TypeID INT,
#Result VARCHAR (1000) OUTPUT
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
IF EXISTS (SELECT ItemName FROM dbo.inv_ItemList WHERE ItemName = RTRIM(#ItemName))
BEGIN
SET #Result = 'Item Name: '+ LTRIM(RTRIM(#ItemName)) + ' ' + 'already exists..'
END
ELSE
BEGIN
INSERT INTO [inv_ItemList] ([ItemName], [TypeID])
VALUES (#ItemName, #TypeID);
SET #Result = 'Item Name: '+ LTRIM(RTRIM(#ItemName)) + ' ' + 'is successfully added..'
End
END
SQL Stored Procedure: inv_ItemList_BindGrid
ALTER PROCEDURE [dbo].[inv_ItemList_BindGrid]
-- Add the parameters for the stored procedure here
#startRowIndex int,
#maximumRows int,
#totalRows int OUTPUT,
#totalRec int OUTPUT
AS
DECLARE #first_id int, #startRow int
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
SET #startRowIndex = ((#startRowIndex - 1) * #maximumRows) + 1
IF #startRowIndex = 0
SET #startRowIndex = 1
SET ROWCOUNT #startRowIndex
-- Insert statements for procedure here
SELECT #first_id = ItemID FROM inv_ItemList ORDER BY ItemID
PRINT #first_id
SET ROWCOUNT #maximumRows
SELECT ItemID, ItemName, inv_TypeList.TypeName FROM inv_ItemList
inner join inv_TypeList on inv_ItemList.TypeID=inv_TypeList.TypeID
WHERE
ItemID >= #first_id
ORDER BY ItemID
SET ROWCOUNT 0
-- GEt the total rows
SELECT #totalRows = COUNT(ItemID) FROM inv_ItemList
SELECT #totalRec = COUNT(*) FROM inv_ItemList
END
Is there anything I missed in my code or any other way to achieved my requirements.
Thank you in advance for your help!
I troubleshoot my code already and I found where the error occurs.
I revised the following SQL statement in my SAVE button
//Method in displaying data in reverse (last - first)
//Calling the database
SqlConnection con2 = new SqlConnection(strConnString);
string strConString = "select * from inv_ItemList order by ItemID DESC";
with this one
string strConString = "SELECT ItemID, ItemName, inv_TypeList.TypeName FROM inv_ItemList inner join inv_TypeList on inv_ItemList.TypeID=inv_TypeList.TypeID order by ItemID DESC";
The error doesn't show up anymore, That's where it solved the error.
Thank you guys for your help!:)
I already have this code to make stringBuilder for every employee, I get all the employeesId from another table . But if I get more than 1000 employees, I get the error ORA-07195 , I know this error is related to a Maximum of expression in a list . Therefore how can I send every 500 employees to my query in Data Access Objects.
Public List<GraphModel> countRequestCreatedByTypeDefaulPage(int year, int month, String employeeID)
{
int count = 0;
int countEmployeess = 0;
string employeesid = "";
DataView dv = _employeeOverrideBO.getRelatedEmployees(year, month, employeeID);
StringBuilder listEmployees = new StringBuilder();
for (int i = 0; i < countEmployees; i += 500)
{
foreach (DataRowView rowView in dv)
{
DataRow row = rowView.Row;
String employee = row["EMPLOYEE_ID"].ToString();
if (count > 0)
listEmployees.Append(",");
listEmployees.Append("'").Append(employee).Append("'");
count++;
}
}
countEmployeess++;
employeesid = listEmployees.ToString();
return _requestDAO.countRequestCreatedByTypeDefaulPage(employeesid);
Also this is my query in Data Access Object
public List<GraphModel> countRequestCreatedByTypeDefaulPage(string employeesIds)
{
String sql = " select NVL(TO_CHAR(RR.REASON_NM_NEW), 'Total') as SERIES1, count(*) AS VAL" +
" from REQUEST R, REQUEST_PERSON RP, REQUEST_REASON RR " +
" WHERE R.STATUS IN ('CREATED', 'PENDING APPROVAL', 'APPROVED BY MANAGER', 'APPROVED', 'IN PROCESS') " +
" AND R.REQUEST_ID = RP.REQUEST_ID" +
" AND RP.REQUEST_ROLE = 'REQUESTOR' " +
" AND RR.REASON_ID = R.REASON_ID" +
" AND RP.EMPLOYEE_ID IN (" + employeesIds + ") " +
" group by rollup (RR.REASON_NM_NEW) " +
" ORDER BY count(*) DESC";
OracleCommand cmd = new OracleCommand(sql);
try
{
DataTable dataTable = Data_base_Access.executeSQL(cmd, ConfigurationManager.ConnectionStrings["stage"].ToString());
return (GraphModel.convertToList(dataTable));
}
catch (Exception ex)
{
Log.writeError("Request DAO", ex);
throw new DataAccessException("There was an error counting the open requests");
}
}
Also this query get the count to list called GraphModel
public static List<GraphModel> convertToList(System.Data.DataTable dataTable)
{
List<GraphModel> list = new List<GraphModel>();
foreach (DataRow dtRow in dataTable.Rows)
{
list.Add(convertToGraphModel(dtRow));
}
return list;
}
public static GraphModel convertToGraphModel(DataRow dtRow)
{
GraphModel graphModel = new GraphModel();
if (dtRow.Table.Columns.Contains("SERIES1") && dtRow["SERIES1"] != DBNull.Value)
{
graphModel.SERIES1 = Convert.ToString(dtRow["SERIES1"]);
}
if (dtRow.Table.Columns.Contains("SERIES2") && dtRow["SERIES2"] != DBNull.Value)
{
graphModel.SERIES2 = Convert.ToString(dtRow["SERIES2"]);
}
if (dtRow.Table.Columns.Contains("VAL") && dtRow["VAL"] != DBNull.Value)
{
graphModel.VAL = Convert.ToInt32(dtRow["VAL"]);
}
return graphModel;
}
}
I really appreciate your help because I am research a lot and I dont know what can I do
Split the list into 1000 item lists and change the query into this:
" AND (RP.EMPLOYEE_ID IN (" + ids_1_1000 + ") OR RP.EMPLOYEE_ID IN (" + ids_1001_2000 + "))" +
One of the features I love most about Oracle is the Oracle Call Interface (OCI) that lets you access some of the more powerful features or Oracle with programming languages. In particular, for this example, the ability to do bulk inserts should prove very helpful.
If, instead of the approach you have above, which is trying to insert thousands of literals into a single SQL statement, you put those values into a table and do a join, I think you will:
Spare the shared pool from having to compile a really nasty SQL statement
Eliminate the need to escape strings or worry about SQL Injection
Have a lightning fast query that substitutes a join (bread and butter for a database) for a giant in-list
Step 1: Create a GTT:
create global temporary table employee_list (
employee_id varchar2(100) not null
) on commit preserve rows;
The GTT is based on a session, so even if you have this code running in multiple instances, each GTT will act as a blank slate for each instance -- no possibility of collisions of data.
Step 2: Within your code, create a transaction to handle the fact that you need the insert to the table and the select on the data to occur as part of the same transaction:
OracleTransaction trans = conn.BeginTransaction(IsolationLevel.ReadCommitted);
Step 3: Use ODP.net's bulk insert capabilities to insert all of your employee Ids at once. I encourage you to benchmark this versus inserting them one at a time. You'll be amazed. If you have more than 50,000, then maybe you need to break the up into chunks, but with a single field, I think this should be more than adequate:
// string[] employeesIds
OracleCommand cmd = new OracleCommand("insert into employee_list values (:EMPLOYEE)",
conn);
cmd.Transaction = trans;
cmd.Parameters.Add(new OracleParameter("EMPLOYEE", OracleDbType.Varchar2));
cmd.Parameters[0].Value = employeesIds;
cmd.ArrayBindCount = employeesIds.Length;
cmd.ExecuteNonQuery();
Note employeeIds should be an array.
Step 4: Change your SQL from an in-list to a join:
select NVL(TO_CHAR(RR.REASON_NM_NEW), 'Total') as SERIES1, count(*) AS VAL
from
REQUEST R,
REQUEST_PERSON RP,
REQUEST_REASON RR,
employee_list e -- added this
WHERE R.STATUS IN ('CREATED', 'PENDING APPROVAL', 'APPROVED BY MANAGER',
'APPROVED', 'IN PROCESS')
AND R.REQUEST_ID = RP.REQUEST_ID
AND RP.REQUEST_ROLE = 'REQUESTOR'
AND RR.REASON_ID = R.REASON_ID
AND RP.EMPLOYEE_ID = e.employee_id -- changed this
group by rollup (RR.REASON_NM_NEW)
ORDER BY count(*) DESC
And here's what it would all look like together:
public List<GraphModel> countRequestCreatedByTypeDefaulPage(string[] employeesIds)
{
OracleTransaction trans = conn.BeginTransaction(IsolationLevel.ReadCommitted);
OracleCommand cmd = new OracleCommand("insert into employee_list values (:EMPLOYEE)",
conn);
cmd.Transaction = trans;
cmd.Parameters.Add(new OracleParameter("EMPLOYEE", OracleDbType.Varchar2));
cmd.Parameters[0].Value = employeesIds;
cmd.ArrayBindCount = employeesIds.Length;
cmd.ExecuteNonQuery();
String sql = ""; // code from above goes here
cmd = new OracleCommand(sql, conn);
cmd.Transaction = trans;
DataTable dataTable = null;
try
{
dataTable = Data_base_Access.executeSQL(cmd,
ConfigurationManager.ConnectionStrings["stage"].ToString());
return (GraphModel.convertToList(dataTable));
}
catch (Exception ex)
{
Log.writeError("Request DAO", ex);
throw new DataAccessException("There was an error counting the open requests");
}
finally
{
trans.Rollback();
}
return dataTable;
}
I resolved my problem with this code..
public List<GraphModel> countRequestCreatedByTypeDefaulPage(int year, int month, String employeeID)
{
int count = 0;
int countEmployees = 0;
Dictionary<string, int> dataChart = new Dictionary<string, int>();
DataView dv = _employeeOverrideBO.getRelatedEmployeesRequests(year, month, employeeID);
StringBuilder listEmployees = new StringBuilder();
foreach (DataRowView rowView in dv)
{
if (countEmployees == 500)
{
List<GraphModel> listReturn = _requestDAO.countRequestCreatedByTypeDefaulPage(listEmployees.ToString());
foreach(GraphModel model in listReturn){
if (dataChart.ContainsKey(model.SERIES1))
{
dataChart[model.SERIES1] = dataChart[model.SERIES1] + model.VAL;
}
else
{
dataChart[model.SERIES1] = model.VAL;
}
}
listEmployees = new StringBuilder();
count = 0;
countEmployees = 0;
}
DataRow row = rowView.Row;
String employee = row["EMPLOYEE_ID"].ToString();
if (count > 0)
listEmployees.Append(",");
listEmployees.Append("'").Append(employee).Append("'");
count++;
countEmployees++;
}
//Last Call
List<GraphModel> listReturnLast = _requestDAO.countRequestCreatedByTypeDefaulPage(listEmployees.ToString());
foreach (GraphModel model in listReturnLast) {
if (dataChart.ContainsKey(model.SERIES1))
{
dataChart[model.SERIES1] = dataChart[model.SERIES1] + model.VAL;
}
else
{
dataChart[model.SERIES1] = model.VAL;
}
}
List<GraphModel> list = new List<GraphModel>();
foreach (KeyValuePair<string, int> entry in dataChart)
{
GraphModel model = new GraphModel();
model.SERIES1 = entry.Key;
model.VAL = entry.Value;
list.Add(model);
}
return list;
}
I work on a search page. I am using 2 repeaters. First to display the results of the search and second to display paging.
The query works just fine if I exclude postback. I can type something in the search box and it appears on the screen. Without the postback, the problem is when I click to go to the second page, I lose the paging repeater. That means I cannot go back to the first page.
So I need this postback to work.
The problem is when the page first loads the text box is empty, therefore I get the following error: "Null or empty full-text predicate."
How to get around it?
Here my code:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
BindRpt();
}
}
private void BindRpt()
{
SqlConnection cn = new SqlConnection(ConfigurationManager.ConnectionStrings["blabla"].ConnectionString);
SqlCommand cmd = new SqlCommand();
cmd.Connection = cn;
SqlDataAdapter adapter = new SqlDataAdapter(cmd);
cmd.CommandText = "select Distinct Rank, columnA, columnB, columnC from FREETEXTTABLE (TABLE, columnA , '" + Search.Text + "' ) S, TABLE C WHERE c.columnID = S.[KEY] order by Rank Desc";
DataTable dt = new DataTable();
adapter.SelectCommand = cmd;
adapter.Fill(dt);
PagedDataSource pgitems = new PagedDataSource();
pgitems.DataSource = dt.DefaultView;
pgitems.AllowPaging = true;
pgitems.PageSize = 2;
pgitems.CurrentPageIndex = PageNumber;
if (pgitems.Count > 1)
{
rptPaging.Visible = true;
ArrayList pages = new ArrayList();
for (int i = 0; i <= pgitems.PageCount - 1; i++)
{
pages.Add((i + 1).ToString());
}
rptPaging.DataSource = pages;
rptPaging.DataBind();
}
else
{
rptPaging.Visible = false;
}
rptResults.DataSource = pgitems;
rptResults.DataBind();
}
public int PageNumber
{
get
{
if(ViewState["PageNumber"] != null)
{
return Convert.ToInt32(ViewState["PageNumber"]);
}
else
{
return 0;
}
}
set
{ ViewState["PageNumber"] = value; }
}
protected void rptPaging_ItemCommand(object source, System.Web.UI.WebControls.RepeaterCommandEventArgs e)
{
PageNumber = Convert.ToInt32(e.CommandArgument) - 1;
BindRpt();
}
protected void btnGo_Click(object sender, EventArgs e)
{
BindRpt();
}
Try adding the following as the first line of BindRpt()
if (string.IsNullOrEmpty(Search.Text)) return;
Update following condition:
if (pgitems.Count > 1)
to
if (pgitems.Count > 0)
Any comments on this code pieces to make it more professional will be gladly accepted. This is why I opened this topic. But the main concern is this; I need to pass item ids, store ids, and start date and end date to get sale records. One of the problem is because of SQL parameter limit (2100), I cannot send more than 2100 parameters to the statement. Now I am trying to receive records store by store (store number is more than 4000 and also item amount). But I could not figure out a good way to do it.
Any one who spent time to help appreciated.
This is data access:
public List<SalesList> ExecuteSales(List<string> items, int storeID, int W1,int W2,int vendorID,int retailerID)
{
SqlCommand command = new SqlCommand();
string statement = "SELECT I.ITEM_NBR,I.ITEM_DESC1,I.ITEM_DESC2,I.VENDOR_STK_NBR,SUM(SA.POS_QTY) AS POS_QTY,SUM(SA.POS_SALES) AS POS_SALES "
+ "FROM SALES_FTBL SA,ITEM_TBL I "
+ "WHERE SA.RETAILER_ID=I.RETAILER_ID "
+ "AND SA.RETAILER_ID = #RetailerID "
+ "AND SA.VENDOR_NBR = #VendorID "
+ "AND SA.STORE_NBR = #StoreID "
+ "AND SA.ITEM_NBR=I.ITEM_NBR "
+"AND SA.ITEM_NBR IN (";
command.Parameters.AddWithValue("#RetailerID", retailerID);
command.Parameters.AddWithValue("#VendorID",vendorID);
command.Parameters.AddWithValue("#StoreID", storeID);
for (int i = 0; i < items.Count; i++)
{
if (i > 0)
{
statement += ", ";
}
string paramStr = "#itemNo" + i;
statement += paramStr;
command.Parameters.Add(paramStr, System.Data.SqlDbType.Int);
command.Parameters[paramStr].Value = items[i];
}
statement += ") ";
//statement += "AND STORE_NBR IN (";
//for (int i = 0; i < stores.Count; i++)
//{
// if (i > 0)
// {
// statement += ", ";
// }
// string paramStr = "#storeNo" + i;
// statement += paramStr;
// command.Parameters.Add(paramStr, System.Data.SqlDbType.Int);
// command.Parameters[paramStr].Value = stores[i];
//}
//statement += ") ";
statement += "AND WEEK IN (";
for (int i = 0; i <1; i++)
{
if (i > 0)
{
statement += ", ";
}
string paramStr = "#W" + i;
statement += paramStr;
command.Parameters.Add(paramStr, System.Data.SqlDbType.Int);
command.Parameters[paramStr].Value = W1;
}
W1=W1+1;
for (int counter=W1; counter < W2;counter++ )
{
if (counter > 0)
{
statement += ", ";
}
string paramStr = "#W" + counter;
statement += paramStr;
command.Parameters.Add(paramStr, System.Data.SqlDbType.Int);
command.Parameters[paramStr].Value = W1++;
}
statement += ") ";
statement += "GROUP BY I.ITEM_NBR,I.VENDOR_STK_NBR,I.ITEM_DESC1,I.ITEM_DESC2 Order By I.ITEM_DESC2 ";
command.CommandText = statement;
command.Connection = connection;
List<SalesList> sales = new List<SalesList>();
SalesList sale;
string itemDescription;
string desc1;
string desc2;
int count = 0;
try
{
connection.Open();
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
sale = new SalesList();
sale.ItemNumber = Convert.ToInt32(reader["ITEM_NBR"].ToString().TrimEnd());
if (reader["ITEM_DESC1"] != null)
{
desc1 = reader["ITEM_DESC1"].ToString().TrimEnd();
}
else { desc1 = ""; }
if (reader["ITEM_DESC2"] != null)
{
desc2 = reader["ITEM_DESC2"].ToString().TrimEnd();
}
else { desc2 = ""; }
if (!desc1.Equals(desc2) || !desc2.Equals(desc1))
{ itemDescription = desc1 + " " + desc2; }
else { itemDescription = desc2; }
sale.ItemDescription2 = itemDescription;
sale.PosQuantity = Convert.ToInt32(reader["POS_QTY"].ToString().TrimEnd());
sale.VendorStockNumber = reader["VENDOR_STK_NBR"].ToString().TrimEnd();
if (reader["POS_SALES"].ToString() != "")
{
sale.PosSales = Convert.ToDouble(reader["POS_SALES"].ToString().TrimEnd());
}
else { sale.PosSales = 0; }
sales.Add(sale);
}
}
catch (SqlException se)
{
Debug.WriteLine("---------- DEBUG INFORMATION ----------");
Debug.WriteLine(se.Message);
Debug.WriteLine("=======================================");
throw se;
}
finally
{
connection.Close();
}
return sales;
}
And this is business layer :
private List<SalesList> ExecuteSales(List<string> items, List<string> stores, string date1, string date2, int vendorID, int retailerID) {
int W1 = CalculateWeek(date1);
int W2 = CalculateWeek(date2);
SalesListDL salesListDO = new SalesListDL();
List<SalesList> sales = new List<SalesList>();
List<SalesList> salesX = new List<SalesList>();
for (int counter = 0; counter < stores.Count; counter++)
{
int storeID = Convert.ToInt32(stores[counter]);
salesX = salesListDO.ExecuteSales(items, storeID, W1, W2, vendorID, retailerID);
if (salesX.Count > 0)
{
foreach (SalesList saleX in salesX.ToList())
{
int index = sales.FindIndex(item => item.ItemNumber == saleX.ItemNumber);
if (index > 0)
{
sales[index].PosQuantity = +saleX.PosQuantity;
sales[index].PosSales = +saleX.PosSales;
salesX.Remove(saleX);
}
else { sales.Add(saleX); }
}
}
}
return sales;
}
Table valued parameters is the way to go if this is indeed the way you need to approach this topic.
First, switch to a stored procedure since you're using SQL 2008 or
newer.
Second, read up on the using statement for disposing of your
sql items.
Psuedo data layer:
public List<SalesList> ExecuteSales(List<string> items, int storeID, int W1, int W2, int vendorID, int retailerID)
{
var sales = new List<SalesList>();
var table = new DataTable();
table.Columns.Add("ItemNumber");
foreach (var item in items)
{
table.Rows.Add(item);
}
using (var connection = new SqlConnection("ConnectionString"))
{
connection.Open();
using (var command = connection.CreateCommand())
{
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "cp_ExecuteSales";
command.Parameters.AddWithValue("#RetailerID", retailerID);
command.Parameters.AddWithValue("#VendorID", vendorID);
command.Parameters.AddWithValue("#StoreID", storeID);
var tvp = new SqlParameter("#ItemIds", SqlDbType.Structured)
{
TypeName = "tvpItems",
Value = table
};
command.Parameters.Add(tvp);
using (var reader = command.ExecuteReader())
{
//DoWork
}
}
}
return sales;
}
Create the tvp:
CREATE TYPE [dbo].[tvpItems] AS TABLE(
[ItemNumber] [int] NULL
)
Create the stored proc:
CREATE PROCEDURE cp_ExecuteSales
#RetailerID VARCHAR(50),
#VendorID VARCHAR(50),
#StoreID VARCHAR(50),
#ItemIds tvpItems READONLY
AS
SELECT I.ITEM_NBR
,I.ITEM_DESC1
,I.ITEM_DESC2
,I.VENDOR_STK_NBR
,SUM(SA.POS_QTY) AS POS_QTY
,SUM(SA.POS_SALES) AS POS_SALES
FROM SALES_FTBL SA
INNER JOIN ITEM_TBL I ON SA.RETAILER_ID = I.RETAILER_ID
AND SA.ITEM_NBR = I.ITEM_NBR
INNER JOIN #ItemIds ID ON SA.ITEM_NBR = ID.ItemNumber
WHERE SA.RETAILER_ID=I.RETAILER_ID
AND SA.RETAILER_ID = #RetailerID
AND SA.VENDOR_NBR = #VendorID
AND SA.STORE_NBR = #StoreID
AND SA.ITEM_NBR=I.ITEM_NBR
If you need to add a second set of number parameters, then you can pass multiple parameters of different types to the database. In the past, we've created several generic types to support varying list of data types rather than having to manage a lot of table types.
CREATE TYPE [dbo].[IntList] AS TABLE(
[Value] [Int] NULL
)
Important things to remember:
The parameter type for a tvp must be SqlDbType.Structured
The TypeName for the parameter must match the Table Value Parameter
type name.
The Table Value Parameter parameter in the stored procedure must be
declared as READONLY
I have a problem and I need your help. As my web service describes I want to get some data and add them to my database.
[WebMethod(Description = "This will input computers into the database", EnableSession = false)]
public string orderItem(int CUS_ID, string COM_ID, int Quantity,double COMPrice)
{
try
{
dbConn = new DbConnection();
SqlConnection conn = dbConn.OpenConnection();
SqlCommand orderItem = new SqlCommand("OrderComputer", conn);
orderItem.CommandType = CommandType.StoredProcedure;
SqlParameter add_CUS_ID = orderItem.Parameters.Add("#CUS_ID", SqlDbType.Int, 4);
add_CUS_ID.Value = CUS_ID;
SqlParameter addBK_ISBN = orderItem.Parameters.Add("#COM_ID", SqlDbType.Char, 80);
addBK_ISBN.Value = COM_ID;
SqlParameter add_Quantity = orderItem.Parameters.Add("#Quantity", SqlDbType.Int, 2);
add_Quantity.Value = Quantity;
SqlParameter add_COMPrice = orderItem.Parameters.Add("#COMPrice", SqlDbType.Money, 8);
add_COMPrice.Value = COMPrice;
return this.ExecuteQuery(orderItem);
}
catch (Exception e)
{
return e.ToString();
}
}
The OrderComputer is a stored procedure:
ALTER Procedure OrderComputer
(
#CUS_ID int,
#COM_ID int,
#Quantity int,
#COMPrice money
)
AS
declare #Date datetime
declare #ShipDate datetime
declare #OR_ID int
select #Date = getdate()
select #ShipDate = getdate()
begin tran NewComputer
INSERT INTO Orders
(
CUS_ID,
Date,
ShipDate
)
VALUES
(
#CUS_ID,
#Date,
#ShipDate
)
SELECT #OR_ID = ##Identity
INSERT INTO ComputerOrders
(
OR_ID,
COM_ID,
Quantity,
COMPrice
)
VALUES
(
#OR_ID,
#COM_ID,
#Quantity,
#COMPrice
)
commit tran NewComputer
The following part is the final step of my shopping cart. It returns a table with the order details. My problem is why the line
order.orderItem(customerID, Computer_ID, quantity, price);
cannot get the record to add it to the database?. Is something missing?
computerOrder1.computerOrder order = new computerOrder1.computerOrder();
int quantity = 2;
XmlDocument customer_Order = ComputerCart.getCartDescription();
while (customer_Order.SelectNodes("//Computers").Count > 0)
{
string Computer_ID = customer_Order.GetElementsByTagName("Computers").Item(0).SelectSingleNode("//com_id").InnerText;
double price = double.Parse(customer_Order.GetElementsByTagName("Computers").Item(0).SelectSingleNode("//price").InnerText);
string Model = customer_Order.GetElementsByTagName("Computers").Item(0).SelectSingleNode("//model").InnerText;
order.orderItem(customerID, Computer_ID, quantity, price);
}
Juding by your comment:
protected string ExecuteQuery(SqlCommand QueryObject) {
int queryResult = QueryObject.ExecuteNonQuery();
if (queryResult != 0) {
return "Your request is CORRECT";
}
else {
return "error: QueryResult= " + queryResult;
}
}
You would need not only your SqlCommand but also your connection
protected string ExecuteQuery(SqlCommand QueryObject, SqlConnection conn) {
try
{
conn.open();
int queryResult = QueryObject.ExecuteNonQuery();
if (queryResult != 0) {
return "Your request is CORRECT";
}
else {
return "error: QueryResult= " + queryResult;
}
}
finally
{
conn.close();
}
}