I tried to convert a datatable that just has one field (the field's data is primary key) to int , in order to using in sql commands such as Select and etc.
but it fails!
and when i cast it to an object or convert it to string first , the commands gone wrong!
please help me
i want to select * from a table which has a foreign key where the foreign code equals by an int value that has been selected from a table in another sql command and returned as a datatable row with just one field.
here is my code :
class mydata :
public string strsql;
public DataTable showData()
{
SqlConnection Con1 = new SqlConnection("Data Source=.;database=daneshgah;integrated security=true");
Con1.Open();
SqlDataAdapter da = new SqlDataAdapter(strsql, Con1);
DataTable dt = new DataTable();
da.Fill(dt);
Con1.Close();
return (dt);
}
button event :
myData search = new myData();
int aa = int.Parse(txt_stdcourse.Text);
search.strsql = "select tchNo from University where couNo='" + aa + "'";
DataTable a = search.showData();
string b = a.Rows[0][0].ToString();
int c = int.Parse(b);
myData akhz = new myData();
akhz.strsql = "insert into stc (couNo,tchNo,stuNo)values('" + aa + "','" + c + "','" + id + "')";
akhz.Data();
lbl_stdcourseok.Visible = false;
lbl_stdcourseok.Visible = true;
Sounds like you need to use ExecuteScalar on a SqlCommand instead of using a DataAdapter. ExecuteScalar gives the first column of the first row of the dataset returned.
public object RunSQL(string sql)
{
SqlConnection Con1 = new SqlConnection("Data Source=.;database=daneshgah;integrated security=true");
Con1.Open();
SqlCommand command = new SqlCommand(strsql, Con1);
return command.ExecuteScalar();
}
//In some event handler
int myValue = (int)RunSQL("Select Value from Table where ID = " + ID);
That said, please don't do that - it is very bad practice. You almost certainly want to create a class that models whatever data objects you are dealing with, instead of executing arbitrary SQL from event handlers. It is also probably best to manage connections independently of your data class, in a separate data access layer.
An extremely rudimentary example:
public class Student
{
public int StudentID { get; set; }
public bool CurrentlyEnrolled { get; set; }
public string Name { get; set; }
public static Student LoadByID(int ID)
{
DataTable results = DAL.ExecuteSQL("Select * from Students WHERE StudentID = #StudentID", new SqlParameter("#StudentID", ID));
if (results.Rows.Count == 1)
{
return FillFromRow(results.Rows[0]);
}
else
{
throw new DataException("Could not find exactly one record with the specified ID.");
}
}
private static Student FillFromRow(DataRow row)
{
Student bob = new Student();
bob.CurrentlyEnrolled = (bool)row["CurrentlyEnrolled"];
bob.Name = (string)row["Name"];
bob.StudentID = (int)row["StudentID"];
return bob;
}
}
public static class DAL
{
private const string ConnectionString = "SomeConnectionString"; //Should really be stored in configuration files.
public static DataTable ExecuteSQL(string SQL, params SqlParameter[] parameters)
{
using (SqlConnection connection = new SqlConnection(ConnectionString))
{
using (SqlCommand command = new SqlCommand(SQL))
{
command.Parameters.AddRange(parameters);
using (SqlDataAdapter adapter = new SqlDataAdapter(command))
{
DataTable result = new DataTable();
adapter.Fill(result);
return result;
}
}
}
}
}
Related
I'm trying to write a function -like Dcount and Dlookup in VBA Access- in a public class to use it everywhere in my project so I did the following :
public class MyTools
{
SqlConnection Cn = new SqlConnection(#"Server = AMR-PC\SQLEXPRESS ; Database=PlanningDB ; Integrated Security = True");
SqlDataAdapter da;
DataTable dt = new DataTable();
// DataView dv = new DataView();
SqlCommand cmd;
SqlDataReader DataRead;
// Variables
string MyColumn, MyTable, MyCondition,DlookResult;
int DcountResult;
// Methods & Functions
// Dcount
public int DCount(string MyColumn, string MyTable, string MyCondition)
{
da = new SqlDataAdapter("Select Count(#MyColumn) from #MyTable where #MyColumn = #MyCondition", Cn);
da.Fill(dt);
DcountResult = int.Parse(dt.Rows[0].ToString());
return DcountResult;
}
}
// Dlookup
}
And tried to use it like this :
int Result = DCount(txtColumn.Text, txtTable.Text, txtCond.Text);
txtResult.Text = null;
txtResult.Text = Result.ToString();
But it throws the error "Must declare the scalar variable "#MyColumn".
I tried to use sqlcommand and DataRead but I need to close the connection after the return and it became Unreachable or close before the return so it returns nothing , That's why i used SqlDataAdapter.
Thanks in advance .
It would have to look something more like this:
public class MyTools
{
private static string ConnectionString {get;} = #"Server = AMR-PC\SQLEXPRESS ; Database=PlanningDB ; Integrated Security = True";
public static int DCount(string MyTable, string MyColumn, string MyCondition)
{
string sql = $"Select Count({MyColumn}) from {MyTable} where {MyColumn} = #MyCondition";
using (var cn = new SqlConnection(ConnectionString))
using (var cmd = new SqlCommand(sql, cn))
{
cmd.Parameters.AddWithValue("#MyCondition", MyCondition);
cn.Open();
return (int)cmd.ExecuteScalar();
}
}
}
Just be aware this uses dynamic SQL, and is more than a little dangerous. In fact, you should not do this. I know you don't want to "keep typing SQL queries", but that might be exactly what you should do.
I need help in reading data from DataTable and adding key, value to a Dictionary object.
//Here is the object:
public class DBName
{
public int ID { get; set; } // key
public string DatabaseName { get; set; } // value
}
My DataTable is getting data, but can't figure out how to add to Dictionary
reading DataTable and adding to Dictionary -
public static Dictionary<int,DBName> ReadToDictionary()
{
string con = #"MyConnectionString;";
SqlConnection sqlconn = new SqlConnection(con);
string sqlQuery = #"SELECT DISTINCT DisplayName AS DatabaseName, RANK() OVER(ORDER BY MIN(id)) AS ID
FROM dbo.MyTable
GROUP BY DisplayName";
Dictionary<int, DBName> dictionaryDBName = new Dictionary<int, DBName>();
SqlCommand sqlcmd = new SqlCommand(sqlQuery, sqlconn);
{
using (SqlDataAdapter da = new SqlDataAdapter(sqlcmd))
{
try
{
DataTable dt = new DataTable();
da.Fill(dt);
foreach (DataRow dr in dt.Rows)
{
foreach (DataColumn col in dt.Columns)
{
//how to add key and Value?
dictionaryDBName.Add(dr[1], DBName);
}
// anything here?
}
}
catch (Exception ex)
{
//
}
finally
{
sqlconn.Close();
}
}
}
return dictionaryDBName;
}
Please guide.
You are probably much better off just using a DataReader. No need to fill a DataTable and then try looping through it, just loop the reader.
Further points:
Don't swallow exceptions, deal with them properly
You need to have a using on the connection, and then you don't need to call Close
Are you aware of the differences between RANK, DENSE_RANK and ROW_NUMBER?
public static Dictionary<int,DBName> ReadToDictionary()
{
string con = #"MyConnectionString;";
using(SqlConnection sqlconn = new SqlConnection(con))
{
string sqlQuery = #"SELECT DISTINCT
DisplayName AS DatabaseName
,CAST(RANK() OVER(ORDER BY MIN(id)) AS int) AS ID
FROM
dbo.MyTable
GROUP BY
DisplayName";
sqlconn.Open();
Dictionary<int, DBName> dictionaryDBName = new Dictionary<int, DBName>();
using(SqlCommand sqlcmd = new SqlCommand(sqlQuery, sqlconn))
using (var reader = sqlcmd.ExecuteReader())
{
while(reader.Read())
{
DBName n = new DBName { ID = reader.GetInt32(1), DatabaseName = reader[0] as string};
dictionaryDBName.Add(n.ID, n);
}
}
return dictionaryDBName;
}
}
Here's the LINQ solution. The key is to use the powerful ToDictionary extension method.:
var reader = sqlCmd.ExecuteReader();
var dataTable = new DataTable()
dataTable.Load(reader);
var dictionary = dataTable.Rows.Cast<DataRow>().ToDictionary
(
x => (int)x[0], //Convert column 0 into the dictionary's key
x => (string)x[1] //Convert column 1 into the dictionary's value
);
However, since SqlDataReader implements IEnumerable, you can skip the data table entirely like this:
var reader = sqlCmd.ExecuteReader();
var dictionary = reader.Cast<IDataRecord>().ToDictionary
(
x => x.GetInt32(0), //Convert column 0 into the dictionary's key
x => x.GetString(1) //Convert column 1 into the dictionary's value
);
See also this answer.
I have two methods that have similar input parameter types, but the parameters themselves are different and used to build an SQL statement within the method.
C# doesn't like this - "Type Database already defines a member called 'DatabaseSearch' with the same parameter types."
As a newbie, this sounds to me like I'm structuring the class or methods wrong?
Should I perhaps be building the SQL statement outside the method and passing it and its parameters in?
// Surname ONLY
public void DatabaseSearch(DataGrid DataGrid, string surname)
{
string database_file_path = #"Data Source=.\MemberDB.db";
string sqlCmd = "Select * FROM Members WHERE Surname = #surname";
using (var con = new SQLiteConnection(database_file_path))
{
using (var cmd = new SQLiteCommand(con))
{
con.Open();
cmd.Parameters.AddWithValue("#surname", surname);
cmd.CommandText = sqlCmd;
var dataAdapter = new SQLiteDataAdapter(cmd);
var dt = new DataTable("Members");
dataAdapter.Fill(dt);
DataGrid.ItemsSource = dt.DefaultView;
dataAdapter.Update(dt);
}
}
}
// Firstname ONLY
public void DatabaseSearch(DataGrid DataGrid, string firstname)
{
string database_file_path = #"Data Source=.\MemberDB.db";
string sqlCmd = "Select * FROM Members WHERE FirstName = #firstname";
using (var con = new SQLiteConnection(database_file_path))
{
using (var cmd = new SQLiteCommand(con))
{
con.Open();
cmd.Parameters.AddWithValue("#firstname", firstname);
cmd.CommandText = sqlCmd;
var dataAdapter = new SQLiteDataAdapter(cmd);
var dt = new DataTable("Members");
dataAdapter.Fill(dt);
DataGrid.ItemsSource = dt.DefaultView;
dataAdapter.Update(dt);
}
}
}
Summary:
How do you have two overloaded methods with the same types of parameters?
public void myMethod( int one, string one){
....some stuff done...
}
public void myMethod( int two, string two){
....different stuff done...
}
You can either change the method name or change the order of the parameters. The first approach is better.
public void DatabaseSearchByFirstName(int one, string one){
// ...some stuff done...
}
public void DatabaseSearchBySurName(int two, string two){
// ...different stuff done...
}
I'm trying to get all data from an SQL table and store it in a List using the C# programming language.
the SQL statement I'm using is:
private string cmdShowEmployees = "SELECT * FROM Employees;";
This is being used in the same class as a function
public List<string> showAllIdData()
{
List<string> id = new List<string>();
using (sqlConnection = getSqlConnection())
{
sqlCommand.Connection = sqlConnection;
sqlCommand.CommandText = cmdShowEmployees;
SqlDataReader reader = sqlCommand.ExecuteReader();
while (reader.Read()) {
id.Add(reader[0].ToString());
}
return id;
}
}
and here
public List<string> showAllActiveData()
{
List<string> active = new List<string>();
using (sqlConnection = getSqlConnection())
{
sqlCommand.Connection = sqlConnection;
sqlCommand.CommandText = cmdShowEmployees;
SqlDataReader reader = sqlCommand.ExecuteReader();
while (reader.Read()) {
active.Add(reader[1].ToString());
}
return active;
}
I would have to create 9 more functions this way in order to get all the data out of the Employees table. This seems very inefficient and I was wondering if there was a more elegant way to do this.
I know using an adapter is one way to do it but I don't think it is possible to convert a filled adapter to a list, list list etc.
SqlDataAdapter adapter = sqlDataCollection.getAdapter();
DataSet dataset = new DataSet();
adapter.Fill(dataset, "idEmployees");
dataGridView1.DataSource = dataset;
dataGridView1.DataMember = "idEmployees";
Any ideas?
If you must use the reader in this way, why not create an object which holds the table row data.
public class SomeComplexItem
{
public string SomeColumnValue { get; set;}
public string SomeColumnValue2 { get; set;}
public string SomeColumnValue3 { get; set;}
public string SomeColumnValue4 { get; set;}
}
That way you can loop through with your reader as follows:
public List<SomeComplexItem> showAllActiveData()
{
List<SomeComplexItem> active = new List<SomeComplexItem>();
using (sqlConnection = getSqlConnection())
{
sqlCommand.Connection = sqlConnection;
sqlCommand.CommandText = cmdShowEmployees;
SqlDataReader reader = sqlCommand.ExecuteReader();
while (reader.Read())
{
var someComplexItem = new SomeComplexItem();
someComplexItem.SomeColumnValue = reader[1].ToString();
someComplexItem.SomeColumnValue2 = reader[2].ToString();
someComplexItem.SomeColumnValue3 = reader[3].ToString();
active.Add(someComplexItem);
}
return active;
}
You could use two select statements to populate two List<string> as shown in the example below where the key between reads is reader.NextResult();.
The database used is the standard Microsoft NorthWind database.
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
namespace SQL_Server_TwoList
{
public class DataOperations
{
public List<string> Titles { get; set; }
public List<string> Names { get; set; }
/// <summary>
/// Trigger code to load two list above
/// </summary>
public DataOperations()
{
Titles = new List<string>();
Names = new List<string>();
}
public bool LoadData()
{
try
{
using (SqlConnection cn = new SqlConnection(Properties.Settings.Default.ConnectionString))
{
string commandText = #"
SELECT [TitleOfCourtesy] + ' ' + [LastName] + ' ' + [FirstName] As FullName FROM [NORTHWND.MDF].[dbo].[Employees];
SELECT DISTINCT [Title] FROM [NORTHWND.MDF].[dbo].[Employees];";
using (SqlCommand cmd = new SqlCommand(commandText, cn))
{
cn.Open();
SqlDataReader reader = cmd.ExecuteReader();
// get results into first list from first select
if (reader.HasRows)
{
while (reader.Read())
{
Names.Add(reader.GetString(0));
}
// move on to second select
reader.NextResult();
// get results into first list from first select
if (reader.HasRows)
{
while (reader.Read())
{
Titles.Add(reader.GetString(0));
}
}
}
}
}
return true;
}
catch (Exception)
{
return false;
}
}
}
}
Form code
namespace SQL_Server_TwoList
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
DataOperations dataOps = new DataOperations();
if (dataOps.LoadData())
{
listBox1.DataSource = dataOps.Names;
listBox2.DataSource = dataOps.Titles;
}
}
}
}
You could always add it all to a dataset or datatable instead of looping through using datareader to add to an array, dataset allows you to access data in similar way to array anyway.
Connstr = "Data Source = " + SelectedIP + "; Initial Catalog = " + dbName + "; User ID = " + txtUsername.Text +"; Password = "+ txtPassword.Text +"";
conn = new SqlConnection(Connstr);
try
{
string contents = "SELECT * FROM ..."
conn.Open();
SqlDataAdapter da_1 = new SqlDataAdapter(contents, conn); //create command using contents of sql file
da_1.SelectCommand.CommandTimeout = 120; //set timeout in seconds
DataSet ds_1 = new DataSet(); //create dataset to hold any errors that are rturned from the database
try
{
//manipulate database
da_1.Fill(ds_1);
if (ds_1.Tables[0].Rows.Count > 0) //loop through all rows of dataset
{
for (int i = 0; i < ds_1.Tables[0].Rows.Count; i++)
{
//rows[rownumber][column number/ "columnName"]
Console.Write(ds_1.Tables[0].Rows[i][0].ToString() + " ");
}
}
}
catch(Exception err)
{}
conn.Close();
}
catch(Exception ex)
{}
I want to build a custom interface (a separate aspx page) to manage the data that is put into the webforms for marketeers (WFFM) database, and that for just one form. It must be possible to edit the data and select records with particular sortings and pagings. The database is configured to be SQLite.
Is this possible and recommended, or is it just plain xml that is saved into the WFFM database? And how should I go about it?
This is completely doable, though the select query to get data out of WFFM is a bit funky because everything is stored loose in one huge table called "field" with only a trail of GUIDs to tie the stored values back to what form they came from and what field.
Provided below is part of an Export to Excel utility I wrote for WFFM data. It builds a DataTable object from submitted form results. You could adapt it to some other structure without much work though.
public string connectionStringWFFM = "user id=sitecore_admin;password=xxx;Data Source=SitecoreDBServer.com;Database=Sitecore_WebForms";
protected DataTable BuildDataTable(Item formItem)
{
List<FormResult> formResults = FormResults(formItem.ID.Guid);
List<Field> distinctFields = DistinctFields(formItem.ID.Guid);
var dt = new DataTable();
dt.Columns.Add("Submission_DateTime", typeof (string));
foreach (Field field in distinctFields)
{
var dataColumn = new DataColumn("_" + field.id.ToString("N"), typeof (string));
dataColumn.Caption = field.name.Replace(" ", "_");
dt.Columns.Add(dataColumn);
}
foreach (FormResult formResult in formResults)
{
var connection = new SqlConnection();
connection.ConnectionString = connectionStringWFFM;
var command = new SqlCommand();
command.Connection = connection;
command.CommandText = "select fieldid, value from field where formid=#formid order by fieldid";
command.Parameters.Add("#formid", SqlDbType.UniqueIdentifier).Value = formResult.id;
connection.Open();
SqlDataReader reader = command.ExecuteReader();
DataRow dataRow = dt.NewRow();
dataRow["Submission_DateTime"] = formResult.timestamp.ToString("MM/dd/yyyy HH:mm:ss");
while (reader.Read())
{
dataRow["_" + reader.GetGuid(0).ToString("N")] = reader.GetValue(1).ToString().Replace("<item>", "").Replace("</item>", "");
}
dt.Rows.Add(dataRow);
reader.Close();
connection.Close();
}
return dt;
}
public List<Field> DistinctFields(Guid formitemid)
{
var connection = new SqlConnection();
connection.ConnectionString = connectionStringWFFM;
var command = new SqlCommand();
command.Connection = connection;
command.CommandText = "select distinct fieldid from field where formid in (select id from form where formitemid=#formitemid) order by fieldid";
command.Parameters.Add("#formitemid", SqlDbType.UniqueIdentifier).Value = formitemid;
connection.Open();
SqlDataReader reader = command.ExecuteReader();
var results = new List<Field>();
int count = 0;
while (reader.Read())
{
var field = new Field();
field.id = reader.GetGuid(0);
Database database = Factory.GetDatabase("master");
Item i = database.GetItem(new ID(field.id));
if (i != null && i.DisplayName != null)
{
field.name = i.DisplayName;
}
else
{
field.name = "Field" + count;
}
results.Add(field);
count += 1;
}
reader.Close();
connection.Close();
return results;
}
public List<FormResult> FormResults(Guid formitemid)
{
var connection = new SqlConnection();
connection.ConnectionString = connectionStringWFFM;
var command = new SqlCommand();
command.Connection = connection;
command.CommandText = "select id, timestamp from form where formitemid=#formitemid";
command.Parameters.Add("#formitemid", SqlDbType.UniqueIdentifier).Value = formitemid;
connection.Open();
SqlDataReader reader = command.ExecuteReader();
var results = new List<FormResult>();
while (reader.Read())
{
var result = new FormResult();
result.id = reader.GetGuid(0);
result.timestamp = reader.GetDateTime(1);
results.Add(result);
}
reader.Close();
connection.Close();
return results;
}
public class FormResult
{
public Guid id { get; set; }
public DateTime timestamp { get; set; }
}
public class Field
{
public Guid id { get; set; }
public string name { get; set; }
}