in C# I'm currently getting some data from SQL, my query returns me only one column due to my select (see code below) but in some case, it could be possible that I have more than one row, so I'd like to know if is there a way to return these row in only one line of text?
Here my current code:
public bool getDBValue(string m_strValue, string m_strFilter, string m_strDBTable, out DataSet m_objDs, out string m_strError)
try
{
using (SqlConnection oConn = new SqlConnection(getConnectionString()))
{
oConn.Open();
SqlDataAdapter l_objAdapter = new SqlDataAdapter("Select [" + m_strValue + "] FROM "+ m_strDBTable+" Where ProjectUID =" + "'" + m_strFilter + "'", oConn);
m_objDs = new DataSet();
l_objAdapter.Fill(m_objDs);
}
return (true);
}
catch (Exception e)
{
m_strError = e.Message;
return (false);
}
Because for the moment, I used my data with with line:
string value = l_objDs.Tables[0].Rows[0]["ColumnName"].ToString();
but as I could have many values, it returns only one values. So any idea of how could I do that?
Thanks.
No it is not possible since you have taking value at Row[0] of Table[0] so you will get value of first row of your first Table.
string value = l_objDs.Tables[0].Rows[0]["ColumnName"].ToString();
i would rather suggest you to iterate over table rows and add it to a StringBuilder and then assign it to the string value.
Something like Below.
StringBuilder sb = new StringBuilder();
foreach (DataRow dr in l_objDs.Tables[0].Rows)
{
sb.Append(dr["ColumnName"]);
}
string value= sb.ToString();
Hope This Helps!
Just use foreach to loop through all rows:
string value = "";
foreach (DataRow row in m_objDs.Tables[0].Rows)
value += row["ColumnName"];
Related
I'm trying to eliminate or put empty an value in my DataGridview if the cell is duplicated. I saw an example but it used GridView in my case is DataGridview. Here is that code:
public void atualiza()
{
try
{
SqlConnection con = new SqlConnection(Login.conectData);
con.Open();
dsFerramenta = new DataSet();
daFerramenta = new SqlDataAdapter("SELECT Ferramentas.Ferramenta_ID, Ferramentas_Terminais.Terminal_ID, Ferramentas_Grupos.Grupo_ID, Vedante_ID, Imagem, Nome_Afinação, Vedante, Observações, Data_Criação, Utilizador FROM Ferramentas "+ "JOIN Ferramentas_Terminais ON Ferramentas_Terminais.Ferramenta_ID = Ferramentas.ferramenta_ID " +
"LEFT JOIN Ferramentas_Grupos ON Ferramentas_Grupos.Ferramenta_ID = Ferramentas.Ferramenta_ID " +
"LEFT JOIN Ferramentas_Vedantes ON Ferramentas_Vedantes.Ferramenta_ID = Ferramentas.Ferramenta_ID " +
"LEFT JOIN FormasCravação ON FormasCravação.Cravação_ID = Ferramentas.Cravação_ID " +
"LEFT JOIN TipoAfinação ON TipoAfinação.Afinação_ID = Ferramentas.Afinação_ID", con);
dsFerramenta.Clear();
daFerramenta.Fill(dsFerramenta, scrollVal, 100, "Ferramentas".Trim());
tabelaRelac.DataSource = dsFerramenta;
tabelaRelac.DataMember = "Ferramentas";
//para organizar as colunas na tabela
tabelaRelac.Columns["Terminal_ID"].DisplayIndex = 1;
tabelaRelac.Columns["Grupo_ID"].DisplayIndex = 2;
tabelaRelac.Columns["Vedante_ID"].DisplayIndex = 3;
tabelaRelac.Columns["Vedante"].DisplayIndex = 4;
tabelaRelac.Columns["Nome_Afinação"].DisplayIndex = 5;
tabelaRelac.Columns["Imagem"].DisplayIndex = 6;
tabelaRelac.Columns["Data_Criação"].DisplayIndex = 7;
tabelaRelac.Columns["Observações"].DisplayIndex = 8;
tabelaRelac.Columns["Utilizador"].DisplayIndex = 9;
con.Close();
string doubleValue = tabelaRelac.Rows[0].Cells[0].ToString().Trim();
for (int i = 0; i < tabelaRelac.Rows.Count; i++)
{
if (tabelaRelac.Rows[i].Cells[0].ToString() == doubleValue)
{
string a = tabelaRelac.Rows[i].Cells[0].ToString().Trim();
a = string.Empty;
}
else
{
doubleValue=tabelaRelac.Rows[i].Cells[0].Value.ToString().Trim();
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
tabelaRelac.ClearSelection();
}
After the con.close(), is my code to eliminate duplicate cell and put an empty value.
I would like some Help.
I use this Video reference to try
I'm using ToString() because DataGridView does't have proprety Text
Thank you.
It is better to handle dublicates in your SQL Query.
Also, Please keep in mind that It is very dangerous to use String Concatenation on SQL Query Generation wince it is open to SQL Injection attacks. Instead use Parameterized Queries.
If you insist on removing dublicates at DataTable level, then I suggest you to look at Ratty's Answer
Here is the code piece from Ratty's post
public DataTable RemoveDuplicateRows(DataTable dTable, string colName)
{
Hashtable hTable = new Hashtable();
ArrayList duplicateList = new ArrayList();
//Add list of all the unique item value to hashtable, which stores combination of key, value pair.
//And add duplicate item value in arraylist.
foreach (DataRow drow in dTable.Rows)
{
if (hTable.Contains(drow[colName]))
duplicateList.Add(drow);
else
hTable.Add(drow[colName], string.Empty);
}
//Removing a list of duplicate items from datatable.
foreach (DataRow dRow in duplicateList)
dTable.Rows.Remove(dRow);
//Datatable which contains unique records will be return as output.
return dTable;
}
So let me first off state that I know there are other questions with the same issue--I've read most of them and tried different things... Nothing worked.. So please don't close because of "Duplicate" because those ARE NOT working for me.
I am also using Postgres as my database.
Thanks for assistance in advanced.
public static string RetrieveEntry(string table, string lookup)
{
Console.WriteLine("RetrieveEntry");
if (!IsConnected())
{
return "Request Failed";
}
string str = "No poll were found that contained that info.";
string sqlstring = "SELECT * FROM "+table+" WHERE topic = '#t' OR description LIKE '#d' OR started_by = '#sb'";
NpgsqlCommand sql = new NpgsqlCommand(sqlstring,conn);
sql.Parameters.AddWithValue("#t", lookup);
sql.Parameters.AddWithValue("#d", "%" + lookup + "%");
sql.Parameters.AddWithValue("#sb", lookup);
NpgsqlDataAdapter adap = new NpgsqlDataAdapter(sqlstring,conn);
DataSet ds = new DataSet();
adap.Fill(ds);
Console.WriteLine("Table: "+ds.Tables[0].TableName+"; Tables: "+ds.Tables.Count+"; Rows: "+ds.Tables[0].Rows.Count);
if (ds.Tables[0].Rows.Count > 0) str = ""; //Remove default string
foreach (DataRow dr in ds.Tables[0].Rows)
{
str += "Topic:\t" + dr["topic"] +
"\nDesc:\t" + dr["description"].ToString().Substring(0, Math.Min(25, dr["description"].ToString().Length)) + "\n\n";
}
return str;
}
Would using a reader fix the issue?
ds.Load(NpgsqlDataReader reader = sql.ExecuteReader(CommandBehavior.CloseConnection));
from this answer
I know it's a bit late, but I really think You shouldn't use the # character in the AddWithValue parameter.
Something like:
sql.Parameters.AddWithValue("t", lookup);
sql.Parameters.AddWithValue("d", "%" + lookup + "%");
sql.Parameters.AddWithValue("sb", lookup);
In my current application I have a snippet of code that allows me to select a single row in a data grid view and store all the columns information into a variable to do with what I want. I use this primarily to send information from one SQL database table to another. It's great for only sending specified cells within a row.
Here is how I do a single row:
string ID = dataGridView1.SelectedRows[0].Cells[0].Value + string.Empty;
string itemOne= dataGridView1.SelectedRows[0].Cells[1].Value + string.Empty;
string itemTwo= dataGridView1.SelectedRows[0].Cells[2].Value + string.Empty;
string itemThree= dataGridView1.SelectedRows[0].Cells[3].Value + string.Empty;
var vItemOne = itemOne;
var vItemTwo= itemTwo;
var vItemThree= itemThree;
// ETC..
However, I now want to be able to select Multiple Rows and only insert specified columns within those rows to a SQL database.
I've tried modifying the above code to work... obviously it doesn't work.
I believe I need a loop, I haven't really used loops much so I'm not sure how to make it loop, skip certain columns, then insert into database.
This is what I am currently attempting, however I seem to be messing up somewhere.
using (SqlConnection con = new SqlConnection(Connection.MTRDataBaseConn))
{
for (int i = 0; i < dataGridView1.SelectedRows.Count; i++)
{
con.Open();
SqlCommand cmd = new SqlCommand();
cmd.CommandText = "INSERT INTO dbo.[" + txtJobName.Text + "] ([Item One], [Item Two], [Item Three]) VALUES(#ItemOne,#ItemTwo,#ItemThree)";
cmd.Connection = con;
string strItemOne = this.dataGridView1.SelectedRows[i].Cells[1].Value + string.Empty;
string strItemTwo = this.dataGridView1.SelectedRows[i].Cells[2].Value + string.Empty;
string strItemThree = this.dataGridView1.SelectedRows[i].Cells[3].Value + string.Empty;
//Parameters
cmd.Parameters.AddWithValue("#ItemOne", strItemOne);
cmd.Parameters.AddWithValue("#ItemTwo", strItemTwo);
cmd.Parameters.AddWithValue("#ItemThree", strItemThree);
//execute
cmd.ExecuteNonQuery();
//close connection
con.Close();
}
}
...
While Debugging My dataGridView.SelectedRows.Count; i++ doesn't seem to be increasing and is staying at 0... I'm receiving the error when I try to return the selected row to a string. Shouldn't my selected rows still return a value?
I'm under the assumption my loop is wrong.
Can anyone help me with my issue?
Simply have to use a for each statement
string itemOne= dataGridView1.SelectedRows[0].Cells[1].Value + string.Empty;
string itemTwo= dataGridView1.SelectedRows[0].Cells[2].Value + string.Empty;
string itemThree= dataGridView1.SelectedRows[0].Cells[3].Value + string.Empty;
var vItemOne = itemOne;
var vItemTwo= itemTwo;
var vItemThree= itemThree;
foreach (DataGridViewRow row in dataGridView1.SelectedRows)
{
//Insert Query Here
}
I know questions this kind are asked from time to time but i can't find any satisfying solution.
How can I open a CSV-File using MS ACE OLEDB 12?
I try it with the following code.
DbConnection connection = new OleDbConnection();
connection.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\\Documents;Extended Properties=\"Text;HDR=Yes\"";
connection.Open();
DbCommand cmd;
cmd = connection.CreateCommand();
cmd.CommandText = "SELECT * FROM [Mappe1#csv]";
DbDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
for (int i = 0; i < reader.FieldCount; i++)
Console.Write("(" + reader.GetValue(i).ToString() + ")");
Console.WriteLine();
}
cmd.Dispose();
connection.Dispose();
Console.WriteLine("Done");
Console.ReadKey();
The Problem is that only one column is found. The Text is delimited by ';'. Even when i specifiy the delimiter with "Delimited(|)" f.e. it will not work.
I can't find any documentation for this provider...
This helped me getting a semicolon-delimited csv to parse in C# using ACE.OLEDB.12.0:
http://sqlserverpedia.com/blog/sql-server-bloggers/use-ace-drivers-and-powershell-to-talk-to-text-files/:
Create a schema.ini text file in the same directory as the csv file you want to import with the following contents:
[fileIwantToImport.csv]
Format=Delimited(;)
ColNameHeader=True
Worked for me. But so yucky.
Seems like the FORMAT=Delimited(;) in the connection string has gone out of fashion...
Try:
connection.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\\Documents;Extended Properties=\"Text;HDR=Yes;FORMAT=Delimited\"";
(inserting "FORMAT=Delimited" into the extended properties of the connection string...)
Have you considered creating DataSet?
public static DataSet ConvertTabFiles(string File, string TableName, string delimiter)
{
//The DataSet to Return
DataSet result = new DataSet();
//Open the file in a stream reader.
StreamReader s;
try
{
s = new StreamReader(#File);
}
catch
{
MessageBox.Show("Can't perform operation on file: " + File);
return result;
}
//Split the first line into the columns
string[] columns = null;
try
{
columns = s.ReadLine().Split(delimiter.ToCharArray());
}
catch
{
MessageBox.Show("Can't parse the file " + File + ", please try again!");
return result;
}
//Add the new DataTable to the RecordSet
result.Tables.Add(TableName);
//MessageBox.Show("Add the new DataTable to the RecordSet");
//Cycle the colums, adding those that don't exist yet
//and sequencing the one that do.
foreach (string col in columns)
{
bool added = false;
string next = "";
int i = 0;
while (!added)
{
//Build the column name and remove any unwanted characters.
string columnname = col + next;
//See if the column already exists
if (!result.Tables[TableName].Columns.Contains(columnname))
{
//if it doesn't then we add it here and mark it as added
result.Tables[TableName].Columns.Add(columnname);
added = true;
}
else
{
//if it did exist then we increment the sequencer and try again.
i++;
next = "_" + i.ToString();
}
}
}
//Read the rest of the data in the file.
string AllData = s.ReadToEnd();
string[] rows = AllData.Split("\r\n".ToCharArray());
//Now add each row to the DataSet
foreach (string r in rows)
{
//Split the row at the delimiter.
string[] items = r.Split(delimiter.ToCharArray());
//Add the item
result.Tables[TableName].Rows.Add(r);
}
//Return the imported data.
return result;
}
I've been at this for few hours now and can't seem to find a solution. I have 2 inventory lists, one a spreadsheet and the other a data table. I need to match the spreadsheet against the data table to find out if I have missing inventory. The spreadsheet should match with what I have in the db, ie the spreadsheet is like a master so when I have missing inventory in DB I need to add it an list and build a report.
I thought by looping throught the spreadsheet and for each inventory in the spreadsheet loop through the data table I can achieve my goal but that proved to be wrong. Any ideas how I would do this?
Thanks,
Eric
Here is the method:
public void Reconcile()
{
ObjectDataSource ods = new ObjectDataSource();
ods.ID = "ods";
ods.TypeName = "";
ods.SelectMethod = "GetAssets";
ods.TypeName = "dsAssetsTableAdapters.AssetsTableAdapter";
ods.SelectParameters.Clear();
ReportDataSource rds = new ReportDataSource("dsAssets_Assets", ods);
reportViewer1.LocalReport.DataSources.Clear();
reportViewer1.LocalReport.DataSources.Add(rds);
string _list = "";
string _list_missing_SN = "";
string filename = Server.MapPath("XLS/reconcile.xls");
string sheetname = GetExcelSheetNames(filename)[0].ToString();
String sConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" +
"Data Source=" + filename + ";" +
"Extended Properties=Excel 8.0;";
OleDbConnection objConn = new OleDbConnection(sConnectionString);
objConn.Open();
OleDbCommand objCmdSelect = new OleDbCommand("SELECT * FROM [" + sheetname + "]", objConn);
OleDbDataAdapter objAdapter1 = new OleDbDataAdapter();
objAdapter1.SelectCommand = objCmdSelect;
DataSet objDataset1 = new DataSet();
objAdapter1.Fill(objDataset1, "XLData");
string m_AssetManagement = System.Configuration.ConfigurationManager.ConnectionStrings["Asset_Management"].ToString();
List<string> SN_list = new List<string>();
SqlDataReader Assets_rd;
SqlCommand cmdMyAssets = new SqlCommand();
cmdMyAssets.Connection = new SqlConnection(m_AssetManagement);
cmdMyAssets.CommandType = CommandType.StoredProcedure;
cmdMyAssets.CommandText = "sp_Assets_Hardware_Select_by_Serial_Number";
try
{
cmdMyAssets.Connection.Open();
Assets_rd = cmdMyAssets.ExecuteReader();
string strString;
while (Assets_rd.Read())
{
strString = Assets_rd.GetSqlString(0).ToString().Trim() + "^" + Assets_rd.GetInt32(1).ToString().Trim() + "^" + Assets_rd.GetInt32(2).ToString().Trim();
SN_list.Add(strString);
}
}
catch (SqlException dbError)
{
Trace.Write("Database unavailable with Message: ", dbError.Message);
Trace.Write("Stack Trace: ", dbError.StackTrace);
throw;
}
bool record_match = false;
foreach (DataRow drXCL in objDataset1.Tables[0].Rows)
{
if (drXCL.ItemArray[1].ToString() != string.Empty)
{
try
{
string[] assetInfo = null;
assetInfo = SN_list[0].Split('^');
if (assetInfo[0].Contains(drXCL.ItemArray[1].ToString()))
{
_list += "|" + drXCL.ItemArray[1].ToString();
}
else
{
_list_missing_SN += drXCL.ItemArray[1].ToString().Trim() + "<br>";
}
}
catch (Exception SqlEx)
{
// Throw Sqw Exception
clAppExceptions.buildEmailNotification(SqlEx.Message.ToString());
}
}
else
{
//_list += "|*** NO SERIAL NUMBER ***";
}
}
if (_list_missing_SN != "")
{
Page.ClientScript.RegisterClientScriptBlock(this.Page.GetType(), "myAlert", "<script language='javascript'>alert('Following Serial Numbers were not on the spreasheet: " + _list_missing_SN + "');</script>");
}
_list += "|";
ods.SelectMethod = "GetAssetsBySerialNumbers";
ods.SelectParameters.Add("list", _list);
reportViewer1.LocalReport.ReportPath = Server.MapPath("~/Reports/Asset_List.rdlc");
ReportParameter rpCategory = new ReportParameter("ReportParameter", "These assets are gone.");
ReportParameter[] _rpCategory = { rpCategory };
reportViewer1.LocalReport.SetParameters(_rpCategory);
reportViewer1.LocalReport.Refresh();
}
I would load the master list into an array and create a second array of bools that correspond to the positions of the first array. Then looping through the datatable, when you find the element, flip the bool to true. If you cannot find it, store that element in a not found array. Once the datatable loop is finished, you can produce 2 lists. The first list is the items in the datatable but not in the master list... the not found array. The second list is created by looping through the bool array, any value of false means that the master list element was not found in the datatable.
This can then be expanded to include counts or other pieces of information that should match but do not.
I'd suggest a different approach. You could copy the data from the database and put it in the spreadsheet on a different worksheet and use the match function. You could also take the data from the spreadsheet and put it in a new table. Then use a query to find discrepencies. I don't think a programming solution is required unless this isn't a one time thing. If this is required for an application of some sort, ignore my answer:)
Don't know if this is of any use but if you have the two lists in IEnumerable sequeneces you could do something simple with LINQ.
I have an extension method I wrote for IEnumerable that I use for this purpose:
public static IEnumerable<T> NotIn<T>(this IEnumerable<T> inputSequence, IEnumerable<T> secondSequence)
{
return secondSequence == null ? new List<T>(inputSequence) : inputSequence.Where(element => !secondSequence.Contains(element));
}
If I recall correctly I ended up finding a native LINQ function that accomplished the same thing but I, of course, forgot what it was
If your just looking for a quick solution, I would just do everything in Excel. It's easy to link Excel to a DB and to link lists.
Link your DB to your Excel file (this way it's always linked to the DB)
Insert a formula to check if the (part, key, etc...) in your master list exists in your list from the DB.
Use this link to see how to link lists in Excel.
Ultimately you have many options. To make a sound decision you need to answer a few questions.
How often will this task need to be performed?
What level of resources do you have available to utilize?
How quickly does this task need to run?
How much data needs to be compared?
Once you have answered these questions, we can suggest a solid solution to you more accurately.
Keep it simple... ADO.Net will probably the simplest approach for this problem. If you fill a DataTable with the values from the spreadsheet (hopefully using OleDb) you will be able to also pull information from the Database (using either OleDb or the correct ADO.Net client.) You can then update the values back into the database for fields such as location or last seen time. These Fill and Update commands can be queries or stored procs.
If you provide more detail such as table schema I could expand my answer further.
Edit...
If you already have one of the sources in a DataTable in .Net you could put both of them in the same DataSet and write a DataView query that would do an outer join. The Outer Join would allow you to see the matched and unmatched values.
Updated...
Sorry it took so long to get back to this. (Started a new job so I have been rather busy.) I am using two spreedsheets, but there is not reason that you couldn't use thie same concept between different databases and even different ADO.Net providers. The basic idea behind this example is to create a LastSeen timestamp in your database. Then instead of looking for what isn't there, you post the latest inventroy back to the database and then query for what hasn't been updated.
var inventoryFile = "Inventory.xlsx"; //ID,Item
var databaseFile = "Database.xlsx"; //ID,Item,Type,SN,LastSeen
var connectionFormatter = "Provider=Microsoft.ACE.OLEDB.12.0;" +
"Data Source=\"{0}\";Mode=ReadWrite;" +
"Extended Properties=\"Excel 12.0 Xml;HDR=Yes;\";";
var inventoryConnectionString = string.Format(connectionFormatter,
inventoryFile);
var databaseConnectionString = string.Format(connectionFormatter,
databaseFile);
using (var inventoryConnection =
new OleDbConnection(inventoryConnectionString))
using (var databaseConnection =
new OleDbConnection(databaseConnectionString))
{
if (inventoryConnection.State != ConnectionState.Open)
inventoryConnection.Open();
if (databaseConnection.State != ConnectionState.Open)
databaseConnection.Open();
var lastSeenCmdString = "SELECT MAX(LastSeen) FROM [Sheet1$]";
var lastSeenCommand = new OleDbCommand(lastSeenCmdString,
databaseConnection);
var lastSeen = lastSeenCommand.ExecuteScalar();
var inventorySelectCmdString = "SELECT ID, Item FROM [Sheet1$]";
var inventoryCmd = new OleDbCommand(inventorySelectCmdString,
inventoryConnection);
var table = new DataTable();
var idCol = table.Columns.Add("ID", typeof(int));
var itemCol = table.Columns.Add("Item", typeof(int));
var inventoryDataAdapter = new OleDbDataAdapter(inventoryCmd);
var databaseDataAdapter = new OleDbDataAdapter();
var updateLastSeenCmdString =
"UPDATE [Sheet1$] SET LastSeen=NOW() WHERE Item=?";
var updateCmd = new OleDbCommand(updateLastSeenCmdString,
databaseConnection);
var parameter = updateCmd.Parameters.Add("Item",
OleDbType.Integer,
0,
"Item");
databaseDataAdapter.UpdateCommand = updateCmd;
inventoryDataAdapter.Fill(table);
table.AcceptChanges();
foreach (var row in table.Rows.OfType<DataRow>())
row.SetModified();
databaseDataAdapter.Update(table);
var notSeenCmdString = "SELECT ID,Item,Type,SN,LastSeen " +
"FROM [Sheet1$]" +
"WHERE LastSeen <= ?";
var notSeenCmd = new OleDbCommand(notSeenCmdString,
databaseConnection);
notSeenCmd.Parameters.Add("LastSeen", OleDbType.Date).Value = lastSeen;
databaseDataAdapter.SelectCommand = notSeenCmd;
var missingInventory = new DataTable();
databaseDataAdapter.Fill(missingInventory);
foreach (var row in missingInventory.Rows.OfType<DataRow>())
Console.WriteLine("ID: {0} Item:{1} Type:{2} SN:{3} LastSeen:{4}",
row.ItemArray);
}