How to check whether table column of the binary type has a value? - sql

The Download command is showing in front of all the rows, I want to show it to only those rows having PDF file attached in the database.
protected void gvupdationsummary_SelectedIndexChanged(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection(st);
con.Open();
SqlCommand com = new SqlCommand("select [name],[data] from [Pragati].[dbo].[Pragati_Status_Updations] where Pragati_no=#Pragati_no", con);
com.Parameters.AddWithValue("Pragati_no", gvupdationsummary.SelectedRow.Cells[3].Text);
SqlDataReader dr = com.ExecuteReader();
if (dr.Read())
{
Response.Clear();
Response.Buffer = true;
//Response.ContentType = dr["type"].ToString();
Response.AddHeader("content-disposition", "attachment;filename=" + dr["name"].ToString());
Response.Charset = "";
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.BinaryWrite((byte[])dr["data"]);
Response.End();
}
else
{
// ...
}
}

The code that you show seems to do the actual PDF download already. There is nothing you can do there to prevent the showing of a download button or link.
Instead you need to change the SQL query that provides data for gvupdationsummary, and add a column such as HasPDF there, like this:
SELECT /* your columns */ ,
CAST(CASE WHEN [data] IS NULL THEN 0 ELSE 1 END AS BIT) AS HasPDF
FROM ....
WHERE ....
Then in your grid rendering code you can use the boolean value of HasPDF to decide if the Download button should be shown.
Using this approach you don't needlessly transfer all PDF binary data from your database to your application, every time the grid is being rendered.

You can use SQLDataReader's IsDBNull method to see whether the column contains non-existent or missing values.
ind idx = dr.GetOrdinal("data");
if (!dr.IsDBNull(idx))
{
// set download link on to response.
}
else
{
}

Related

Display the latest updated data

I have to display the data that currently being updated in the text file. The problem is, I'm using the CONVERT function for the columns that I need to display. The data that being displayed is System.Byte[]. The actual data that I need to display is a varbinary string.
-- This query is displaying the data before updating the status.
query = SELECT CONVERT(varchar(10), Start_RG, 2) AS Start_RG, CONVERT(varchar(10), End_RG, 2) AS End_RG, Status FROM RG WHERE Status = 'New';
command = new SqlCommand(query, cnn);
dR = command.ExecuteReader();
if (dR.HasRows)
{
dR.Close();
-- This is the query for updating the status to 'In Use'. I'm using the OUTPUT clause to display the data that has been update.
sql = UPDATE TOP (1) RG SET Status = 'In Use' OUTPUT deleted.Start_RG, deleted.End_RG, deleted.Status WHERE Status = 'New';
cmd= new SqlCommand(sql, cnn);
dataReader = cmd.ExecuteReader();
using (StreamWriter tw = File.AppendText(Path))
{
while (dataReader.Read())
{
tw.WriteLine("assign..\n");
tw.WriteLine("Start RG: {0}", Convert.Tostring((byte[])dataReader["Start_RG"]));
tw.WriteLine("End RG: {0}", Convert.Tostring((byte[])dataReader["End_RG"]));
}
}
}
How can I fetch the Start_RG and End_RG that currently updated the status to In Use? Any other suggestion that I can use instead of OUTPUT clause?
Whatever you are doing using OUTPUT clause is fine. For reading byte[] to string, you can use below approach. Leveraged Stackoverflow answer: https://stackoverflow.com/a/4959269/634935
tw.WriteLine("Start RG: {0}", Encoding.ASCII.GetString(((byte[])dataReader["Start_RG"])); //based on encoding, you need to choose appropriate static method
tw.WriteLine("End RG: {0}", Encoding.ASCII.GetString(((byte[])dataReader["End_RG"]));

WPF DataGrid deleted rows don't get updated (deleted) in the database

I have a DataGrid in my application, whose XML definition is as follows:
<DataGrid x:Name="grid"
DockPanel.Dock="Top"
Visibility="{Binding gridVisibility}"
CellStyle="{StaticResource ValidationReadyCellStyle}"
IsSynchronizedWithCurrentItem="True"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch"
ColumnWidth="*"
ItemsSource="{Binding DBtable, ValidatesOnExceptions=False,
NotifyOnSourceUpdated=True, TargetNullValue={x:Static system:String.Empty}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
AutoGenerateColumns="True" AutoGeneratingColumn="grid_OnAutoGeneratingColumn" CanUserAddRows="True"
BeginningEdit="grid_OnBeginningEdit" PreviewKeyDown="grid_OnPreviewKeyDown" RowEditEnding="grid_OnRowEditEnding" CellEditEnding="grid_OnCellEditEnding">
<DataGrid.RowValidationRules>
<local:RowValidationChecker ValidationStep="UpdatedValue"/>
</DataGrid.RowValidationRules>
</DataGrid>
As can be seen, the ItemsSource is bound to a table named DBtable, depending on which the rows/columns are automatically generated. Following is the code snippet used for connecting to and updating the database:
public bool SaveToDB(DataTable table, string tableName)
{
var msSqlConnectionClass = new MsSqlConnectionClass(MsSqlLogin.Default.Server,
MsSqlLogin.Default.LoremIpsumDB, MsSqlLogin.Default.UID,
MsSqlLogin.Default.Password, MsSqlLogin.Default.WinAuth);
SqlConnection msSqlConnection = msSqlConnectionClass.getMsSqlConnection();
msSqlConnection.Open();
try
{
string strSQL = "SELECT * FROM " + tableName;
SqlDataAdapter da = new SqlDataAdapter(strSQL, msSqlConnection);
SqlCommandBuilder command = new SqlCommandBuilder(da);
da.UpdateCommand = command.GetUpdateCommand();
da.DeleteCommand = command.GetDeleteCommand();
da.InsertCommand = command.GetInsertCommand();
da.Update(table);
msSqlConnection.Close();
}
catch (Exception e)
{
ServiceLog.AddLogInfo(e.ToString());
msSqlConnection.Close();
return false;
}
return true;
}
The problem is, although any addition or edit operation done in the DataGrid gets perfectly updated in the database, I am unfortunately unable to achieve the same behaviour for the deletion operation. The deletion is done in the source itself, so when I check the row count after a deletion operation (for which I use DBtable.Rows.RemoveAt()), DBtable shows me that the row is deleted, however the changes are not reflected in the database after the update attempt made using the SaveToDB() function shown above. What should I do?
I found the problem. Apparently
Dbtable.Rows.RemoveAt(selectedIndex);
does not let the data table know that a deletion command has been issued. Hence, when an update command is run over the database, no deletion is seen and executed. Instead, using
row = DBtable.Rows[selectedIndex];
row.Delete();
solved the problem.
Something similar confused me as well. Here is a solution for those who may encounter this page while searching later.
public DataTable GetMembers()
{
conn = new SqlCeConnection(#"Data Source = DataModel.sdf");
dataAdapter = new SqlCeDataAdapter("Select * from Members", conn);
commandBuilder = new SqlCeCommandBuilder(dataAdapter);
dataTable = new DataTable();
dataAdapter.Fill(dataTable);
dataTable.RowChanged += new DataRowChangeEventHandler(dataTable_RowChanged);
dataTable.RowDeleted += new DataRowChangeEventHandler(dataTable_RowDeleted);
dataTable.DefaultView.ListChanged += DefaultView_ListChanged;
return dataTable;
}
void DefaultView_ListChanged(object sender, System.ComponentModel.ListChangedEventArgs e)
{
if (e.ListChangedType == System.ComponentModel.ListChangedType.ItemDeleted)
{
try
{
dataAdapter.Update(dataTable);
}
catch (Exception ex)
{
System.Windows.MessageBox.Show(ex.Message);
}
}
}

How to fix this error ''reader' is a 'variable' but is used like a 'method''

I am using a C# class.Everythink working fine but i am facing this error, so please help to fix this error.
public void Filldropdownlist(DropDownList ddl, string DisplayVal, string Qstr)
{
try
{
CreateConn();
SqlCommand cmd = new SqlCommand(Qstr, constr);
SqlDataReader reader = cmd.ExecuteReader();
ddl.Items.Clear();
ddl.Items.Add(new ListItem(DisplayVal, "none"));
while (reader.Read())
{
ddl.Items.Add(new ListItem(reader(0).ToString(), reader(1).ToString()));
ddl.DataTextField = reader(0).ToString();
ddl.DataValueField = reader(1).ToString();
}
}
catch (Exception ex)
{
}
finally
{
CloseConn();
}
}
problem coming in inside the while loop.
Indexing in C# is done with the [] operator, not with the () operator as in, for example Visual Basic.
In essence
reader(0)
means "call the method reader with and argument 0" and
reader[0]
means give me value with the index 0 within the variable reader.
Aside from that, the DataTextField and the DataValueField are used only if you are data-binding the drop down, not if you are manually inserting the items, so those two lines can be omitted.
They are also incorect, because they need to be set to the name of the fields, not to their values
Change like this:
while (reader.Read())
{
ddl.Items.Add(new ListItem(reader[0].ToString(), reader(1).ToString()));
ddl.DataTextField = reader[0].ToString();
ddl.DataValueField = reader[1].ToString();
}
use [] instead of ()

GetOleDbSchemaTable(OleDbSchemaGuid.Indexes, ...) always returning zero rows access database

When querying an Access 2000 database, using:
schemaTable = cn.GetOleDbSchemaTable(OleDbSchemaGuid.Indexes, New Object() {Nothing, Nothing, tableName})
Where cn is a valid and open connection, schemaTable always contains zero rows, despite the tableName specified having many indexes.
This documentation, here http://msdn.microsoft.com/en-us/library/cc668764.aspx suggests that MS Access provides this information.
What gives?
It appears that when retrieving .Indexes the third member of the restrictions array corresponds to the Index name, not the Table name. So to retrieve the indexes for a given table it looks like we need to retrieve all of the indexes (no restrictions) and then filter out the ones we don't want.
The following C# code works for me:
using (OleDbConnection con = new OleDbConnection())
{
con.ConnectionString = myConnectionString;
con.Open();
object[] restrictions = new object[3];
System.Data.DataTable table = con.GetOleDbSchemaTable(OleDbSchemaGuid.Indexes, restrictions);
// Display the contents of the table.
foreach (System.Data.DataRow row in table.Rows)
{
string tableName = row[2].ToString();
if (tableName == "Clients")
{
foreach (System.Data.DataColumn col in table.Columns)
{
Console.WriteLine("{0} = {1}",
col.ColumnName, row[col]);
}
Console.WriteLine("============================");
}
}
con.Close();
}

C# Sql Data not saving

I have a few tables in a c# application I'm currently working on and for 4/5 of the tables everything saves perfectly fine no issues. For the 5th table everything seems good until I reload the program again (without modifying the code or working with a seperate install so that the data doesn't go away) The 4/5 tables are fine but the 5th doesn't have any records in it after it has been restarted (but it did the last time it was running). Below is some code excerpts. I have tried a few different solutions online including creating a string to run the sql commands on the database manually and creating the row directly as opposed to the below implementation which uses a generic data row.
//From main window
private void newInvoice_Click(object sender, EventArgs e)
{
PosDatabaseDataSet.InvoicesRow newInvoice = posDatabaseDataSet1.Invoices.NewInvoicesRow();
Invoices iForm = new Invoices(newInvoice, posDatabaseDataSet1, true);
}
//Invoices Table save [Works] (from Invoices.cs)
private void saveInvoice_Click(object sender, EventArgs e)
{
iRecord.Date = Convert.ToDateTime(this.dateField.Text);
iRecord.InvoiceNo = Convert.ToInt32(this.invoiceNumField.Text);
iRecord.Subtotal = (float) Convert.ToDouble(this.subtotalField.Text);
iRecord.Tax1 = (float)Convert.ToDouble(this.hstField.Text);
iRecord.Total = (float)Convert.ToDouble(this.totalField.Text);
iRecord.BillTo = this.billToField.Text;
invoicesBindingSource.EndEdit();
if (newRecord)
{
dSet.Invoices.Rows.Add(iRecord);
invoicesTableAdapter.Adapter.Update(dSet.Invoices);
}
else
{
string connString = Properties.Settings.Default.PosDatabaseConnectionString;
string queryString = "UPDATE dbo.Invoices set ";
queryString += "Date='" + iRecord.Date+"'";
queryString += ", Subtotal=" + iRecord.Subtotal;
queryString += ", Tax1=" + iRecord.Tax1.ToString("N2");
queryString += ", Total=" + iRecord.Total;
queryString += " WHERE InvoiceNo=" + iRecord.InvoiceNo;
using (SqlConnection dbConn = new SqlConnection(connString))
{
SqlCommand command = new SqlCommand(queryString, dbConn);
dbConn.Open();
SqlDataReader r = command.ExecuteReader();
dbConn.Close();
}
}
dSet.Invoices.AcceptChanges();
}
//Invoice Items save [works until restart] (also from Invoices.cs)
private void addLine_Click(object sender, EventArgs e)
{
DataRow iRow = dSet.Tables["InvoiceItems"].NewRow();
iRow["Cost"] = (float)Convert.ToDouble(this.costField.Text);
iRow["Description"] = this.descriptionField.Text;
iRow["InvoiceNo"] = Convert.ToInt32(this.invoiceNumField.Text);
iRow["JobId"] = Convert.ToInt32(this.jobIdField.Text);
iRow["Qty"] = Convert.ToInt32(this.quantityField.Text);
iRow["SalesPerson"] = Convert.ToInt32(this.salesPersonField.Text);
iRow["SKU"] = Convert.ToInt32(this.skuField.Text);
dSet.Tables["InvoiceItems"].Rows.Add(iRow);
invoiceItemsTableAdapter.Adapter.Update(dSet,"InvoiceItems");
PosDatabaseDataSet.InvoiceItemsDataTable dTable = (PosDatabaseDataSet.InvoiceItemsDataTable)dSet.InvoiceItems.Copy();
DataRow[] d = dTable.Select("InvoiceNo=" + invNo.ToString());
invoiceItemsView.DataSource = d;
}
Thanks in advance for any insight.
UPDATE: October 17, 2011. I am still unable to get this working is there any more ideas out there?
you must execute your Sql Command in order to persis the changes you made.
using (SqlConnection dbConn = new SqlConnection(connString))
{
dbConn.Open();
SqlCommand command = new SqlCommand(queryString, dbConn);
command.ExecuteNonQuery();
dbConn.Close();
}
The ExecuteReader method is intended (as the name says) to read the data from a SQL table. You need to use a different method as you can see above.
We need some more info first, you haven't shown the case where your code fails.
Common mistakes on this kind of code is calling DataSet.AcceptChanges() before actually committing the changes to the database.
Second is a conflict between databound data through the binding source vs edits to the dataset directly.
Lets see the appropriate code and we can try and help.
Set a breakpoint after teh call to invoiceItemsTableAdapter and check the InvoiceItems table for the row you have added. Release the breakpoint and then close your app. Check the database again. I would say that another table may be forcibly overwriting the invoice item table.