I have a dataset called "dts_Material_Report" which is used to generate reports.In that data set I have a tableAdapter called "dt_report_Received_Materials".
Previously I have load the data to that table adapter with following code ,
private void generate_report( string qry )
{
string query, qry1;
query = qry;
int pr_id = Form_Common_PCM.pr_id;
clz_Common_SqlConnection con = new clz_Common_SqlConnection();
SqlDataAdapter sda = new SqlDataAdapter(query, con.ActiveCon());
DataSet dts = new DataSet();
sda.Fill(dts, "dt_report_Received_Materials");
rdc.SetDataSource(dts);
crystalReportViewer1.ReportSource = rdc;
crystalReportViewer1.DisplayToolbar = true;
crystalReportViewer1.Show();
}
But currently I am having all the data which I need to generate the report in one of my data table called "dt_mat_cost".
int Ref_ID_s_category;
Ref_ID_s_category = Convert.ToInt16(cbo_sub_category .SelectedValue );
int pro_id = Form_Common_PCM.pr_id;
clz_Received_Material_Summary rms = new clz_Received_Material_Summary();
DataTable dt_mat_cost = rms.Summary_Material_Cost_Filter_By_Project_By_Sub_Category(Ref_ID_s_category);
Now i want to load those data from "dt_mat_cost" to my tableAdapter "dt_report_Received_Materials" .Is there any way to do this.
Thanks in Advance.
One way to resolve this would be to put the DataTable into a DataSet and then run the crystal code as shown below. You may be able to just set the ReportSource to the datatable but I do not recall off the top of my head if that will work.
DataTable dt_matCost = rms.Summary_Material_Cost_Filter_By_Project_By_Sub_Category(Ref_ID_s_category);
DataSet dts = new DataSet();
dts.Tables.Add(dt_matCost);
//ds.Tables[0].TableName = "Whatever CR thinks it is"; // may need to set for CR
rdc.SetDataSource(dts);
crystalReportViewer1.ReportSource = rdc;
crystalReportViewer1.DisplayToolbar = true;
crystalReportViewer1.Show();
Related
in database i have a column id and a column pic of table gambar. Column pic is a column of string that are converted of images, i want to put the id and picin a datagridview, but the pic containing string, so i have to convert it first using base64, but i dont know how to display it to datagridview
code :
using (MySqlConnection mysqlCon = new MySqlConnection(ConfigurationManager.ConnectionStrings["konekKuy"].ConnectionString))
{
mysqlCon.Open();
string insertQuery = "SELECT * FROM gambar";
MySqlCommand command = new MySqlCommand(insertQuery, mysqlCon);
MySqlDataAdapter sqlDa = new MySqlDataAdapter(command);
DataTable dtblLaris = new DataTable();
sqlDa.Fill(dtblLaris);
if (dtblLaris.Rows.Count > 0)
{
dataGridView1.DataSource = dtblLaris;
dataGridView1.Columns["id"].HeaderText = "ID";
dataGridView1.Columns["pic"].HeaderText = "PHOTO";
byte[] imageBytes = Convert.FromBase64String(dataGridView1.Columns[1].ToString());
using (var ms = new MemoryStream(imageBytes, 0, imageBytes.Length))
{
Image image = Image.FromStream(ms, true);
}
DataGridViewImageColumn imageColumn = new DataGridViewImageColumn();
imageColumn = (DataGridViewImageColumn)dataGridView1.Columns[1];
imageColumn.ImageLayout = DataGridViewImageCellLayout.Stretch;
}
sqlDa.Dispose();
mysqlCon.Close();
}
do you know any better ways to display it on datagridview?
I think the code as it is should work fine... but it is pretty unstructured and hard to read / understand
First of all it is always good practise to seperate your code into dedicated methods. This is a common principle in software engineering called Single Responsibility Principle
If we apply the principle to your code it would look something like this:
private void Load()
{
// 1) Execute Sql query
DataTable originDataTable = QueryData("konekKuy", "SELECT * FROM gambar");
// 2) If query returns results
if (originDataTable.Rows.Count > 0)
{
// 3) Convert queried DataTable to DataTable with Image
DataTable convertedDataTable = ConvertDataTable(originDataTable);
// 4) Set the converted DataTable as DataGridView DataSource
LoadDataIntoDataGrid(convertedDataTable);
}
else
{
MessageBox.Show("No data to display!");
}
}
public DataTable QueryData(string connectionString, string queryCommand)
{
DataTable dataTable = new DataTable();
using (var sqlConnection = new MySqlConnection(ConfigurationManager.ConnectionStrings[connectionString].ConnectionString))
{
MySqlCommand command = new MySqlCommand(queryCommand, sqlConnection);
MySqlDataAdapter adapter = new MySqlDataAdapter(command);
sqlConnection.Open();
adapter.Fill(dataTable);
adapter.Dispose();
sqlConnection.Close();
}
return dataTable;
}
public DataTable ConvertDataTable(DataTable originDataTable)
{
// Create the new DataTable with their uppercase titles and their new types.
var convertedDataTable = new DataTable();
convertedDataTable.Columns.Add("ID", typeof(string));
convertedDataTable.Columns.Add("PHOTO", typeof(Image));
// Loop through original DataTable rows and convert base64 string to Image with 'ConvertBase64ToImage' method
foreach (DataRow dataRow in originDataTable.Rows)
{
var id = dataRow.Field<string>("id");
var image = ConvertBase64ToImage(dataRow.Field<string>("pic"));
convertedDataTable.Rows.Add(id, image);
}
return convertedDataTable;
}
public Image ConvertBase64ToImage(string base64)
{
var bytes = Convert.FromBase64String(base64);
using (var memory = new MemoryStream(bytes, 0, bytes.Length))
{
return Image.FromStream(memory, true);
}
}
public void LoadDataIntoDataGrid(DataTable convertedDataTable)
{
dataGridView1.DataSource = convertedDataTable;
}
The QueryData would contain all code which is responsible to get your data from the database. After the SQL query has been executed the QueryData method return the DataTable which contains the data from your database
ConvertDataTable method takes the DataTable from the database query and creates a new DataTable which holds the same data like the original DataTable except the Base64 string will be converted to a Image
ConvertBase64ToImage contains the code that converts the base64 string to a Image file and returns the Image
The LoadDataIntoDataGrid method accepts a DataTable as parameters and handels the insertion of the data into the UIs DataGridView
Creating dedicated methods for each action / responsibility makes your code much easier to understand and maintain. It also makes your code testable through UnitTests which is a big deal!
I hope this helped you clean up your code
Is there a way, where I can use a sql adapter and convert the sql query results into a Data Columns? I'm kinda new a datatables. I need to build this dynamically since my column names are stored into a sql table. I keep running into datarows not columns. What I have built so far:
string feedcolumns = #"select FeedColumnName from myTable where FeedProcessID = #feedprocessid";
SqlCommand columnscommand = new SqlCommand(feedcolumns, connUpd);
DataTable dt = new DataTable("datafeed");
foreach(DataColumn dc in dt.Columns)
{
dc = new
dt.Columns.Add(dc);
}
You can fill a DataTable directly from an SqlReader, no need to go column by column.
One thing I did notice was that your SQL statement had a parameter in it that was never assigned to the command object, so I added it in
string feedcolumns = "select FeedColumnName from myTable where FeedProcessID = #feedprocessid";
DataTable dt = new DataTable("datafeed");
using (SqlConnection connUpd = new SqlConnection("MyConnection")) {
using (SqlCommand columnscommand = new SqlCommand(feedcolumns, connUpd)) {
columnscommand.Parameters.AddWithValue("#feedprocessid", feedprocessid);
connUpd.Open();
var dataReader = columnscommand.ExecuteReader();
dt.Load(dataReader);
}
}
I want to put several buttons on my WPF form and update dynamically my DataGrid with the data from a different database for each button, let say, I have 3 databases and 3 buttons, and when you push one button you get the data from 1 different database.
But I want the data on the DataGrid to update back into the database when a change is made on the Grid, so I don't have to program all the "save" stuff.
Right now, the code that I have is this:
try
{
OleDbConnection conn = new OleDbConnection(
"Provider=Microsoft.Jet.OLEDB.4.0; " +
"Data Source=MaterialDB.mdb");
OleDbDataAdapter adapter = new OleDbDataAdapter("SELECT * FROM myTable", conn);
myDataSet = new DataSet();
adapter.Fill(myDataSet, "myTable");
var be = CatalogsGrid.GetBindingExpression(DataGrid.ItemsSourceProperty);
CatalogsGrid.DataContext = myDataSet;
CatalogsGrid.ItemsSource = myDataSet.Tables[0].DefaultView;
Binding nbe = new Binding();
nbe.Source = myDataSet;
nbe.Mode = BindingMode.TwoWay;
nbe.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
nbe.Path = new PropertyPath("myTable");
nbe.BindsDirectlyToSource = true;
CatalogsGrid.SetBinding(DataGrid.ItemsSourceProperty, nbe);
CatalogsGrid.Items.Refresh();
}
This code loads the data from a database into the grid, but I edit the data and it doesn't update back into the MS Access table.
Oh, it is still not coded but the "myTable" should be a string where I put the name of the different tables I want to show and update from the grid.
What am I missing?
The DataGrid does not save changes automatically, that's up to you (your application) to decide, but it writes back changes to the underlying DataTable.
So as I understand, you want to avoid having a save button and save changes back to the database immediately after they have changed. What you need now is to know when something has changed, and your DataSet can help you with that:
myDataSet = new DataSet();
myDataTable = myDataSet.Tables["myTable"];
adapter.Fill(myDataTable);
// Update the DB whenever a row changes
myDataTable.OnRowChanged += (s, e) =>
{
adapter.Update(myDataTable);
}
Create a centralized method that will update the data that is used to bind the data. Create a save button and call the below function. It will save the network traffic for being save the data on every change.
public void UpdateDb ( OleDbDataAdapter adap, DataSet ds)
{
var build= new OleDblCommandBuilder (adap);
adap.Update (ds);
}
Just you need to pass the parameter and it will update the changes made to dataset.
Taking #Bernhard answer as a starting point, had to add the update command and some tweaking, it is now working.
This is the final code:
try
{
OleDbConnection conn = new OleDbConnection(
"Provider=Microsoft.Jet.OLEDB.4.0; " +
"Data Source=MaterialDB.mdb");
//conn.Open();
OleDbDataAdapter adapter = new OleDbDataAdapter("SELECT * FROM myTable", conn);
myDataSet = new DataSet();
adapter.Fill(myDataSet, "myTable");
DataTable myDataTable = myDataSet.Tables["myTable"];
// Create the UpdateCommand.
OleDbCommand command = new OleDbCommand(
"UPDATE myTable SET Type = #Type, Description = #Description " +
"WHERE ID = #ID", conn);
// Add the parameters for the UpdateCommand.
command.Parameters.Add("#Type", OleDbType.Char, 255, "Type");
command.Parameters.Add("#Description", OleDbType.Char, 255, "Description");
command.Parameters.Add("#ID", OleDbType.Integer, 5, "ID");
adapter.UpdateCommand = command;
// Update the DB whenever a row changes
myDataTable.RowChanged += (s, f) =>
{
adapter.Update(myDataTable);
};
var be = CatalogsGrid.GetBindingExpression(DataGrid.ItemsSourceProperty);
CatalogsGrid.DataContext = myDataSet;
CatalogsGrid.ItemsSource = myDataSet.Tables[0].DefaultView;
Binding nbe = new Binding();
nbe.Source = myDataSet;
nbe.Mode = BindingMode.TwoWay;
nbe.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
nbe.Path = new PropertyPath("myTable");
nbe.BindsDirectlyToSource = true;
CatalogsGrid.SetBinding(DataGrid.ItemsSourceProperty, nbe);
CatalogsGrid.Items.Refresh();
}
Thanks for the help.
(First of all I'm so sorry about my english, because I'm a stranger and I don't know well)
I'm working in a school project. But I need to set a DataTable as DataSource in ReportViewer. First the user type the ID of the Document, and click on the button, the button calls an class that do a select in my database and return 12 fields. I've created a DataSet with all fields that the select results and I've selected it as the Report DataSource. But I need to transfer the data of the select to the DataSet, because when I start my application the Report has an error. Here is the code, and I hope you can help me! Thanks.
Buttton Code:
SelectDocumento doc = new SelectDocumento();
doc.ImprimirDoc(int.Parse(txtID.Text));
Class that select data in my database:
public void ImprimirDoc(int id)
{
string pesquisar = "CALL SP_Imprimir_Documento(" + id + ")";
MySqlConnection con;
con = new MySqlConnection("Persist Security Info=false; server=localhost; database=hospital; uid=root; pwd=");
MySqlDataAdapter adapter = new MySqlDataAdapter(pesquisar, con);
DataTable dt = new DataTable();
dt.TableName = "DataSet1";
con.Open();
adapter.Fill(dt);
ImprimirDocumento imprimir = new ImprimirDocumento(dt);
imprimir.ShowDialog();
}
Code of the Report Form:
private DataTable proc;
public ImprimirDocumento(DataTable select)
{
InitializeComponent();
proc = select;
}
ConexaoHospital bd = new ConexaoHospital();
SelectDocumento doc = new SelectDocumento();
private void ImprimirDocumento_Load(object sender, EventArgs e)
{
this.rptDocumento.RefreshReport();
this.rptDocumento.LocalReport.DataSources.Clear();
Microsoft.Reporting.WinForms.ReportDataSource rprtDTSource = new Microsoft.Reporting.WinForms.ReportDataSource("DataSet1", proc);
this.rptDocumento.LocalReport.DataSources.Add(rprtDTSource);
this.rptDocumento.RefreshReport();
}
Error that the Report Displays:
Error
If someone have a simmilar problem this way of my post is correct and my problem was because my ReportViewer DataSet name was different than my DataTable. My DataTable name was "DataSet1" and my DataSet name was "Documento". I changed the DataSet name for "DataSet1" and it works.
I am using SqlBulkCopy object to write a datatable into an sql server table. However, everytime I recheck my database it remains intact with no changes. A
I have tried to do Google search to determine my problem but i am unable to resolve it.
The datatable came from an .xls file.
public static DataTable dt = new DataTable();
private void ExportToGrid(String path, String filen)
{
int idx = filen.IndexOf(".");
string tf = filen.Remove(idx, 4);
OleDbConnection MyConnection = null;
DataSet DtSet = null;
OleDbDataAdapter MyCommand = null;
MyConnection = new OleDbConnection("provider=Microsoft.Jet.OLEDB.4.0; Data Source='" + path + "';Extended Properties=Excel 8.0;");
ArrayList TblName = new ArrayList();
MyConnection.Open();
DataTable schemaTable = MyConnection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" });
foreach (DataRow row in schemaTable.Rows)
{
TblName.Add(row["TABLE_NAME"]);
}
MyCommand = new System.Data.OleDb.OleDbDataAdapter("select * from [" + TblName[0].ToString() + "]", MyConnection);
DtSet = new System.Data.DataSet();
MyCommand.Fill(DtSet);
MyCommand.FillSchema(DtSet, SchemaType.Source);
DataTable dt = new DataTable();
dt = DtSet.Tables[0];
Session["dt"] = dt;
int x = dt.Rows.Count;
MyConnection.Close();
if (dt.Rows.Count > 0)
{
theGridView.DataSource = dt;
theGridView.DataBind();
}
if (System.IO.File.Exists(path))
{
System.IO.File.Delete(path);
}
}
This is my writer function
private void StartImport()
{
string servername = server;
string database = database;
string tbl = "dbo.LinkDb";
Stopwatch sw = new Stopwatch();
sw.Start();
SqlBulkCopy bulkCopy = new SqlBulkCopy("Data Source=" + servername + ";Initial Catalog=" + database + ";Integrated Security=SSPI", SqlBulkCopyOptions.TableLock);
bulkCopy.DestinationTableName = tbl;
bulkCopy.WriteToServer(dt);
sw.Stop();
lblResult.Visible = true;
lblResult.Text = (sw.ElapsedMilliseconds / 1000.00).ToString();
}
Below are the screenshot of the tables stored in my sql server. I assure you that I have been complying to Case Sensitive rules.
There was no exception thrown and average time elapsed is 0.018 - 0.020 secs
Appreciate any helps.
Thank you
Based on the code you have posted, you are writing an empty datatable to the database. Your "ExportToGrid" method fills dt, a DataTable declared locally, which loses scope outside of the method. Your write function is calling the static DataTable dt which is a new datatable.
Does dt need to be static? it seems as though this could be declared as
private DataTable dt;
then inside "ExportToGrid" instead of declaring another DataTable just instantiate the already declared dt rather than declaring a new one
dt = new DataTable();
Alternatively you could extract the DataTable straight from the GridView during the write Method:
DataTable dt = (DataTable)theGridView.DataSource;
bulkCopy.WriteToServer(dt);
This removes the need for variables outside of the scope of the method.
Lastly since you are storing your datatable within the session (I am not generally an advocate of storing large amounts of data in session variables but without knowing the specifics of your site I cannot really pass judgement), you could use the following:
DataTable dt = (DataTable)Session["dt"];
bulkCopy.WriteToServer(dt);
I dont see anything obvious compared to my use except for the fact that I explicitly map columns from the data table to the database table.
Using cn As New SqlConnection(DataAccessResource.CONNECTIONSTRING)
cn.Open()
Using copy As New SqlBulkCopy(cn)
copy.BulkCopyTimeout = 300
copy.ColumnMappings.Add(0, 0)
copy.ColumnMappings.Add(1, 1)
copy.ColumnMappings.Add(2, 2)
copy.ColumnMappings.Add(3, 3)
copy.DestinationTableName = "Tablename"
copy.WriteToServer(dataset.datatable)
End Using
End Using
Connection string (sql server 2000!) looks like
"data source=DBSERVERNAME;initial catalog=DBNAME;persist security info=True;user id=USERNAME;password=PASSWORD;packet size=4096"
I doubt the connection string is a problem assuming youve used it elsewhere.
Finally have you checked the data types for the columns in the dataset datatable match the ones in the database. In my experience oledb load from excel does not always produce output you might expect, date fields and columns with mixed text and numbers being perticular problems.