I am coding win form app, which checks on startup right of the currently logged user. I had these right saved in MS SQL server in the table. When importing data to Datatable, there is no problem. But when I want to read value, there is message "cannot find column xy".
SqlDataAdapter sdaRights = new SqlDataAdapter("SELECT * FROM rights WHERE [user]='" + System.Security.Principal.WindowsIdentity.GetCurrent().Name + "'", conn);
DataTable dtRights = new DataTable(); //this is creating a virtual table
sdaRights.Fill(dtRights);
Object cellValue = dt.Rows[0][1];
int value = Convert.ToInt32(cellValue);
MessageBox.Show(value.ToString());
I would like, that program would save the value from SQL to int.
You are assuming that you have rows being returned, would be my first guess. You should loop through your DataTable instead of simply trying to access element 0 in it.
DataTable dtRights = new DataTable();
sdaRights.Fill(dtRights);
foreach(DataRow row in dtRights.Rows) {
Object cellValue = row[1];
int value = Convert.ToInt32(cellValue);
MessageBox.Show(value.ToString());
}
using (SqlConnection con = new SqlConnection("your connection string"))
{
using (SqlCommand cmd = new SqlCommand("SELECT [column_you_want] FROM [rights] WHERE [user] = #user"))
{
cmd.Parameters.AddWithValue("#user", System.Security.Principal.WindowsIdentity.GetCurrent().Name);
con.Open();
int right = Convert.ToInt32(cmd.ExecuteScalar());
}
}
Related
The following C# code runs a DAX statement and retrieves a DataTable. This works fine, but now I need to retrieve from the database up to N rows. Is there a way to limit the number of rows returned by the Fill function? If not, how can I retrieve the top N rows? Note that I need to keep this generic for any DAX statement, so you shouldn't change the DAX itself. Also, I don't want to retrieve all the data and then take the first N rows as the data may be too large.
public static DataTable runDaxStatement(int maxRows) {
var con = ConfigurationManager.ConnectionStrings["Default"].ConnectionString;
AdomdConnection conn = new AdomdConnection(con);
DataSet ds = new DataSet();
ds.EnforceConstraints = false;
AdomdCommand cmd = new AdomdCommand("evaluate customers", conn);
AdomdDataAdapter da = new AdomdDataAdapter(cmd);
da.Fill(ds);
return ds.Tables[0];
}
Came across the following TOPN function in the documentation.
This can be used to return the top N rows of the specified table.
For example
public static DataTable runDaxStatement(int maxRows) {
var connectionString = ConfigurationManager.ConnectionStrings["Default"].ConnectionString;
using(AdomdConnection connection = new AdomdConnection(connectionString)) {
string commandText = $"EVALUATE TOPN({maxRows}, customers, <orderBy_expression_here>)";
AdomdCommand command = connection.CreateCommand();
command.CommandText = commandText;
DataSet dataSet = new DataSet(){
EnforceConstraints = false
}
AdomdDataAdapter adapter = new AdomdDataAdapter(command);
adapter.Fill(dataSet);
return dataSet.Tables[0];
}
}
I am running a SQL Query which will return a count the query is
Select Count(numstudents) from classA
I am using C# to connect to SQL Server and execute this query, but my issue is, how do I get the actual number returned? My current method returns the number of rows in the DataTable which by default will always be 1. I need to get the Count() returned.
Here is full C# syntax:
private void GetData()
{
DataSet ds = new DataSet()
using (var con = new SqlConnection(connectionString))
{
using (var cmd = new SqlCommand("RunAStoredProc", con))
{
using (var da = new SqlDataAdapter(cmd))
{
cmd.CommandType = CommandType.StoredProcedure;
da.Fill(ds);
}
}
}
DataTable table1 = new DataTable();
table1 = ds.Tables[0];
DataTable table2 = new DataTable();
table2 = ds.Tables[1];
string numberreturned = table1.Rows.Count.ToString();
Console.WriteLine(numberreturned);
Console.ReadKey();
}
Stored procedure reads like such:
Alter Procedure [dbo].[GetData]
As
Select Count(*) FROM classA
Select studentfirstname, studentlastname FROM classA
Where enrolled = 'Yes'
You don't need an SqlDataAdapter and all the infrastructure required to work with if you just have a single value returned by your Stored Procedure. Just use ExecuteScalar
int count = 0;
using (var con = new SqlConnection(connectionString))
using (var cmd = new SqlCommand("RunAStoredProc", con))
{
cmd.CommandType = CommandType.StoredProcedure;
count = (int)cmd.ExecuteScalar();
}
Console.WriteLine(count);
Console.ReadKey();
However if your really want to use an adapter and a dataset then you can find the result of your query reading the value from the first row and first column from the returned table
int count = Convert.ToInt32(table1.Rows[0][0]);
or even (without declaring the table1 variable)
int count = Convert.ToInt32(ds.Tables[0].Rows[0][0]);
To discover the difference between the result of the first select statement and the count of rows returned in the second select statement you could write
int allStudents = Convert.ToInt32(ds.Tables[0].Rows[0][0]);
int enrolledStudents = ds.Tables[1].Rows.Count;
int notEnrolledStudents = allStudents - enrolledStudents;
The following coding doesn't update my table. But rows variable value is 1 after updating.
I cannot understand what is the cause behind this. Please help.
SqlConnection connection1 = new SqlConnection(connectionString);
connection1.Open();
var wktbl = new DataTable();
var cmd = new SqlCommand("SELECT * FROM Test", connection1);
var da1 = new SqlDataAdapter(cmd);
var b = new SqlCommandBuilder(da1);
da1.Fill(wktbl);
wktbl.Rows[0][2] = "5";
da1.UpdateCommand = b.GetUpdateCommand(true);
int rows = da1.Update(wktbl);
Check this page out. It shows the example below of doing an update with the dataadapter.
The following examples demonstrate how to perform updates to modified rows by explicitly setting the UpdateCommand of a DataAdapter and calling its Update method. Notice that the parameter specified in the WHERE clause of the UPDATE statement is set to use the Original value of the SourceColumn. This is important, because the Current value may have been modified and may not match the value in the data source. The Original value is the value that was used to populate the DataTable from the data source.
private static void AdapterUpdate(string connectionString)
{
using (SqlConnection connection =
new SqlConnection(connectionString))
{
SqlDataAdapter dataAdpater = new SqlDataAdapter(
"SELECT CategoryID, CategoryName FROM Categories",
connection);
dataAdpater.UpdateCommand = new SqlCommand(
"UPDATE Categories SET CategoryName = #CategoryName " +
"WHERE CategoryID = #CategoryID", connection);
dataAdpater.UpdateCommand.Parameters.Add(
"#CategoryName", SqlDbType.NVarChar, 15, "CategoryName");
SqlParameter parameter = dataAdpater.UpdateCommand.Parameters.Add(
"#CategoryID", SqlDbType.Int);
parameter.SourceColumn = "CategoryID";
parameter.SourceVersion = DataRowVersion.Original;
DataTable categoryTable = new DataTable();
dataAdpater.Fill(categoryTable);
DataRow categoryRow = categoryTable.Rows[0];
categoryRow["CategoryName"] = "New Beverages";
dataAdpater.Update(categoryTable);
Console.WriteLine("Rows after update.");
foreach (DataRow row in categoryTable.Rows)
{
{
Console.WriteLine("{0}: {1}", row[0], row[1]);
}
}
}
}
I found the problem. It's because connectionString has |DataDirectory|.
The MDF file location is different when running the application.
I am trying to get column names for particular data table.
I tried with this code.
datagridFieldCreation.AutoGenerateColumns = false;
DataTable dt = new DataTable();
SqlDataAdapter sda = new SqlDataAdapter("select * from Add_Information ", con);
sda.Fill(dt);
datagridFieldCreation.DataSource = dt;
I am getting full data that is there in table. But I want only column names to be displayed one by one. Can any one help me out??
You can use ExecuteReader(CommandBehavior.SchemaOnly)):
DataTable schema = null;
using (var con = new SqlConnection(connection))
{
using (var schemaCommand = new SqlCommand("SELECT * FROM Add_Information", con))
{
con.Open();
using (var reader = schemaCommand.ExecuteReader(CommandBehavior.SchemaOnly))
{
schema = reader.GetSchemaTable();
}
}
}
datagridFieldCreation.DataSource = schema;
SchemaOnly:
The query returns column information only. When using SchemaOnly, the
.NET Framework Data Provider for SQL Server precedes the statement
being executed with SET FMTONLY ON.
The column name is in the first column of every row.
foreach (DataRow col in schema.Rows)
{
Console.WriteLine("ColumnName={0}", col.Field<String>("ColumnName"));
}
Adpated from: Using GetSchemaTable() to retrieve only column names
You can use:
SELECT * FROM YOURTABLENAME WHERE 0=1
Yes for sure, it is simple query which has a conditional statement which is always returning false, so each time you execute the query no rows will be extracted and only columns you will get so you can easily put up these columns in you DataGridView.
I'm looking at the example here:
http://msdn.microsoft.com/en-US/library/y06xa2h1(v=vs.80).aspx
string s = "primaryKeyValue";
DataRow foundRow = dataSet1.Tables["AnyTable"].Rows.Find(s);
if (foundRow != null)
{
MessageBox.Show(foundRow[1].ToString());
}
else
{
MessageBox.Show("A row with the primary key of " + s + " could not be found");
}
They don't specify where does dataSet1 come from and does this represent some database?
I'm trying to use this example in my code to find unique rows but I can't seem to implement this syntax. I'm only using connection string to open connection to SQL and I use SqlDataAdapter to perform functions...
EDIT:
SqlConnection myConnection = new SqlConnection("Data Source=server; Initial Catalog=Dashboard; Integrated Security=SSPI; Persist Security Info=false; Trusted_Connection=Yes");
SqlDataAdapter da = new SqlDataAdapter();
try
{
//Opens the connection to the specified database
myConnection.Open();
//Specifies where the Table in the database where the data will be entered and the columns used
da.InsertCommand = new SqlCommand("INSERT INTO DashboardLibAnswer(Id,Date,Time,Question,Details,Answer,Notes,EnteredBy,WhereReceived,QuestionType,AnswerMethod,TransactionDuration)"
+ "VALUES(#Id,#Date,#Time,#Question,#Details,#Answer,#Notes,#EnteredBy,#WhereReceived,#QuestionType,#AnswerMethod,#TransactionDuration)", myConnection);
//Specifies the columns and their variable type where the data will be entered
//Special note: Conversion from String > DateTime will cause exceptions that will only import some part of data and not everything
da.InsertCommand.Parameters.Add("#Id", SqlDbType.NVarChar);
da.InsertCommand.Parameters.Add("#Date", SqlDbType.Text);
da.InsertCommand.Parameters.Add("#Time", SqlDbType.Text);
da.InsertCommand.Parameters.Add("#Question", SqlDbType.Text);
da.InsertCommand.Parameters.Add("#Details", SqlDbType.Text);
da.InsertCommand.Parameters.Add("#Answer", SqlDbType.Text);
da.InsertCommand.Parameters.Add("#Notes", SqlDbType.Text);
da.InsertCommand.Parameters.Add("#EnteredBy", SqlDbType.NVarChar);
da.InsertCommand.Parameters.Add("#WhereReceived", SqlDbType.NVarChar);
da.InsertCommand.Parameters.Add("#QuestionType", SqlDbType.NVarChar);
da.InsertCommand.Parameters.Add("#AnswerMethod", SqlDbType.NVarChar);
da.InsertCommand.Parameters.Add("#TransactionDuration", SqlDbType.NVarChar);
//Using the global variable counter this loop will go through each valid entry and insert it into the specifed database/table
for (int i = 0; i < counter; i++)
{
//Iterates through the collection array starting at first index and going through until the end
//and inserting each element into our SQL Table
DataSet dashboardDS = new DataSet();
da.Fill(dashboardDS, "DashboardLibAnswer");
DataTable dt = dashboardDS.Tables["DashboardLibAnswer"];
foreach (DataColumn col in dt.Columns)
{
if (col.Unique)
{
da.InsertCommand.Parameters["#Id"].Value = collection.getIdItems(i);
da.InsertCommand.Parameters["#Date"].Value = collection.getDateItems(i);
da.InsertCommand.Parameters["#Time"].Value = collection.getTimeItems(i);
da.InsertCommand.Parameters["#Question"].Value = collection.getQuestionItems(i);
da.InsertCommand.Parameters["#Details"].Value = collection.getDetailsItems(i);
da.InsertCommand.Parameters["#Answer"].Value = collection.getAnswerItems(i);
da.InsertCommand.Parameters["#Notes"].Value = collection.getNotesItems(i);
da.InsertCommand.Parameters["#EnteredBy"].Value = collection.getEnteredByItems(i);
da.InsertCommand.Parameters["#WhereReceived"].Value = collection.getWhereItems(i);
da.InsertCommand.Parameters["#QuestionType"].Value = collection.getQuestionTypeItems(i);
da.InsertCommand.Parameters["#AnswerMethod"].Value = collection.getAnswerMethodItems(i);
da.InsertCommand.Parameters["#TransactionDuration"].Value = collection.getTransactionItems(i);
da.InsertCommand.ExecuteNonQuery();
}
}
//Updates the progress bar using the i in addition to 1
_worker.ReportProgress(i + 1);
} // end for
//Once the importing is done it will show the appropriate message
MessageBox.Show("Finished Importing");
} // end try
catch (Exception exceptionError)
{
//To show exceptions thrown just uncomment bellow line
//rtbOutput.AppendText(exceptionError.ToString);
} // end catch
//Closes the SQL connection after importing is done
myConnection.Close();
}
if you populate a dataset from your data adapter, you'll be able to follow the same logic -
http://msdn.microsoft.com/en-us/library/bh8kx08z(v=vs.71).aspx
It might be worth showing what you actually have to get more specific help
EDIT
I think I'm understanding what you want - if you fill your datatable from the already populated table, just check the item doesn't already exist before adding it - i.e.
if (dt.Rows.Find(collection.getIdItems(i)) == null)
{
// add your new row
}
(just to be sure I knocked together a quick test - hopefully this helps):
// MyContacts db has a table Person with primary key (ID) - 3 rows - IDs 4,5,6
SqlConnection myConnection = new SqlConnection("Data Source=.; Initial Catalog=MyContacts; Integrated Security=SSPI; Persist Security Info=false; Trusted_Connection=Yes");
SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = new SqlCommand("select * from Person", myConnection);
myConnection.Open();
DataSet dashboardDS = new DataSet();
da.Fill(dashboardDS, "Person");
dashboardDS.Tables[0].PrimaryKey = new[] { dashboardDS.Tables[0].Columns["ID"]};
List<int> ids = new List<int> {4, 6, 7};
foreach (var id in ids)
{
if (dashboardDS.Tables[0].Rows.Find(id) == null)
{
Console.WriteLine("id not in database {0}", id); //i.e. 7
}
}
You will first need to open a connection to your database. This is an excellent source for connection strings: The Connection String Reference.
Then you will need to fill the dataset with data from some table. Since we are only interested in the schema information we are only selecting one row (SELECT TOP 1 ...).
Then we can go through the columns and check their Unique property (Boolean):
string connString =
"server=(local)\\SQLEXPRESS;database=MyDatabase;Integrated Security=SSPI";
string sql = #"SELECT TOP 1 * FROM AnyTable";
using (SqlConnection conn = new SqlConnection(connString)) {
conn.Open();
SqlDataAdapter da = new SqlDataAdapter(sql, conn);
using (DataSet ds = new DataSet()) {
da.Fill(ds, "AnyTable");
DataTable dt = ds.Tables["AnyTable"];
foreach (DataColumn col in dt.Columns) {
if (col.Unique) {
Console.WriteLine("Column {0} is unique.", col.ColumnName);
}
}
}
}
UPDATE #1
Sorry, I missunderstood your question. The above example returns unique columns, not unique rows. You can get unique (distinct) rows by using the DISTINCT keyword in SQL:
SELECT DISTINCT field1, field2, field3 FROM AnyTable
You can then fill the data table the same way as above.
Usually the word "unique" is used for unique constraints and unique indexes in database jargon. The term "distinct" is used for rows which are different.
UPDATE #2
Your updated question seems to suggest that you don't want find unique rows, but that you want to insert unique rows (which is the exact opposite).
Usually you would select distinct items from a collection like this. However it is difficult to answer your question accurately, since we don't know the type of your collection.
foreach (var item in collection.Distinct()) {
}
UPDATE #3
The easiest way to insert distinct values in the SQL Server table is to filter the rows at their origin, when reading them from the CSV-File; even before splitting them.
string[] lines = File.ReadAllLines(#"C:\Data\MyData.csv");
string[][] splittedLines = lines
.Distinct()
.Select(s => s.Split(','))
.ToArray();
Now you have distinct (unique) splitted lines that you can insert into the SQL Server table.