I have function in SQL as above, i want the value 'INTERNATIONAL' stored in the string('strIntlStudent'). How can i accomplish that? I know data reader but column has no name.
string TSQL_INTERNATIONAL = "select TOP 1 campus6.dbo.fndqgetpopulation_of_YT_v2a ('P000170620', '2017', '03TERM')";
DataTable DT_INTERNATIONAL = dhelper.ExecuteSelectCommand(TSQL_INTERNATIONAL, CommandType.Text);
if (DT_INTERNATIONAL != null && DT_INTERNATIONAL.Rows.Count > 0)
{
strIntlStudent = DT_INTERNATIONAL.Rows[0]["it says no column name"].ToString();
}
You need to give your column a name. Try this:
select TOP 1 campus6.dbo.fndqgetpopulation_of_YT_v2a
('P000170620', '2017', '03TERM') AS some_name
Then you can use that name:
strIntlStudent = DT_INTERNATIONAL.Rows[0]["some_name"].ToString();
Alternatively, if you are only retrieving one value, then you can use ExecuteScalar function which returns one value regardless of the column name and you don't need to bother with a table. Check your dhelper class to see if it has a function related to ExecuteScalar.
Related
I'm filling a datagrid in c# from a SQLite database, but SQLite databases have no true boolean value, so I've made an SQLite INTEGER field with a check to ensure it is 0 or 1. Instead of show that 0 or 1 in the datagrid, I'd like to show a Yes/no. 1=Yes, 0=No. I'd like the data in the DB to stay the same, just change what is displayed to the user. The sql statement filling the table right now is a simple one:
SELECT * FROM TABLE1
What would be the best way to achieve this? Thank you.
EDIT:
The field in question is the "Injured" field.
Table Schema:
CREATE TABLE "SmashRoster" (
"SmashRosterID" INTEGER PRIMARY KEY AUTOINCREMENT,
"CharacterName" TEXT NOT NULL,
"TotalTournaments" INTEGER NOT NULL,
"Wins" INTEGER NOT NULL,
"Losses" INTEGER NOT NULL,
"Championships" INTEGER NOT NULL,
"InjuriesCaused" INTEGER NOT NULL,
"Injured" INTEGER NOT NULL DEFAULT 0 CHECK(Injured IN (0,1))
);
Method used to pull the data from the DB, Bind to the datagrid is at the bottom:
SQLiteConnection cnn = new SQLiteConnection(#"Data
Source=C:\SQLiteDB\SQLiteDB.db;Version=3;");
SQLiteCommand cmd;
SQLiteDataReader dataReader;
DataTable roster;
cnn.Open();
cmd = new SQLiteCommand(#"SELECT * FROM SmashRoster", cnn);
roster = new DataTable();
dataReader = cmd.ExecuteReader();
roster.Load(dataReader);
dataReader.Close();
cmd.Dispose();
cnn.Dispose();
rosterGridView.DataSource = roster;
Assuming the data value is an integer as you say, you can use the CellFormatting event of the DataGridView control like this:
private void grid_CellFormatting(object sender, ataGridViewCellFormattingEventArgs e)
{
if ( e.ColumnIndex == columnIndex )
if ( e.Value is int )
e.Value = (int)e.Value == 0 ? "No" : "Yes";
}
All values other than 0 are considered true else you can modify the test as you want.
Replace columnIndex by the index you need starting from 0.
Also replace the int check and cast by long if you use a SQLite x64 driver.
You can also use the column name like this:
if ( (sender as DataGridView)?.Columns[e.ColumnIndex].Name == "column name" )
Or the binded data property name from your query:
if ( (sender as DataGridView)?.Columns[e.ColumnIndex].DataPropertyName == "name" )
Using column index or name you are independant from the query.
Using data property name you are independant from the columns order and naming.
You may choose what you prefer.
Depending of the situation.
You could use a case expression directly in the sql statement. See https://www.sqlitetutorial.net/sqlite-case/
If you use some business object layer, you could have a specific property to expose this field as a calculated string instead of a integer. With ADO.NET Dataset/Datatable, you could have the same behaviour with Expression column https://learn.microsoft.com/en-us/dotnet/framework/data/adonet/dataset-datatable-dataview/creating-expression-columns
You could use the CellFormatting event of the datagridview to spot the right column and convert the Int to a String.
Am trying to get a a Zero indexed Value from a column in the TableAdpter but it has refused , how can i retrieve a value in the Column index Zero , below is my code :
LoginTableAdapter l = new LoginTableAdapter();
string res = l.GetData("mueat", "1234").Rows[0].ToString();
And my table which is attached to the TableAdapter is as below , it's one column and i want to get the value t which is in a Zero index in the column access:
If we assume l.GetData("mueat", "1234") returns a DataTable, like so:
DataTable table = l.GetData("mueat", "1234"); // the dataTable
then this:
DataRow row = table.Rows[0]; // first row;
will only give you the first row out of the DataRowCollection's indexer
As we can see on the DataRow type, it has an indexer as well, giving access to the columns in the DataRow instance.
object columnValue = row[0]; // first column
You can now cast the object value to the correct type or call ToString on it to convert it to its string representation.
Putting this all back together in your compact one-liner you will get:
string res = l.GetData("mueat", "1234").Rows[0][0].ToString();
I understand this method of getting DB data (using foreach):
var db = Database.Open("Connection");
var rows = db.Query("SELECT 1 columnName,2 columnName2 FROM Table");
foreach(var row in rows){
var data = row.columnName;
//or
var data = row[0];
}
This works, but how do I get the data without using a foreach?
var data = rows[0][1];
^ This doesn't work.
Basically, I am trying to figure out how to get the data without using a foreach. What would I have to do?
EDIT:
.Query() returns:
Type: System.Collections.Generic.IEnumerable
The rows returned by the SQL query.
As shown here: http://msdn.microsoft.com/en-us/library/webmatrix.data.database.query%28v=vs.111%29.aspx
You can use the ElementAt method to get to the row then use indexing to get to the column of that row:
var data = rows.ElementAt(0)[0];
You can even reference the columns by name as you are actually receiving an IEnumerable<dynamic>:
var row = rows.ElementAt(0);
//now you can access:
//row.columnName
//row.columnName2
Using ToArray() on your collection is an option;
var results = db.Query("SELECT * FROM Table").ToArray();
Console.WriteLine(results[1][2]);
This will allow you to reference your result set the way you want. However, if you don't bound your collection in the query somehow, you could end up loading a large collection into memory to reference it this way. I've never seen the WebMatrix Database before, so I can't give any tips on doing this in the most efficient manner, but ToArray() will give you what you want.
db.Query actually returns type DynamicRecord, so if you want to reference your column names by name, you can do;
var results = db.Query("SELECT * FROM Table").Cast<DynamicRecord>().ToArray();
Console.WriteLine(results[0]["Id"]);
Now you can use column names
And as petelids mentions,
IEnumerable<dynamic> results = db.Query("SELECT * FROM Table");
Console.WriteLine(results.ElementAt(0).Id);
If you are wanting a specific answer for the WebMatrix.Data example, then this won't help you at all.
However, if you like writing actual SQL statements, but don't like tedious mapping code, then I like to use micro-ORMs like OrmLite, PetaPoco, Massive, Dapper, etc...
This is an example using my favorite: http://www.toptensoftware.com/petapoco/
http://www.nuget.org/packages/petapoco
/// <summary>
/// Create a Poco mapping class where the class name matches the Table name
/// and the properties match the column names and data types from the table
/// </summary>
public class Table{
public int ColumnName {get;set;}
public int ColumnName2 {get;set;}
}
int id = 1;
var db = new Database("Connection Name");
const string sql = #"SELECT
1 columnName,
2 columnName2
FROM Table
WHERE ColumnName = #0";
return db.FirstOrDefault<Table>(sql, id);
or
// Using auto-generated Select statement
return db.FirstOrDefault<Table>("WHERE ColumnName = #0", id);
// Fetch all records...
return db.Fetch<Table>("");
// PetaPoco also supports dynamic
return db.FirstOrDefault<dynamic>(sql, id);
What does db.Query returns is some information we need.
What you can try is fill your result in a datatable.
And then getting it back like this:
DataTable dt = db.Query("SELECT 1 columnName,2 columnName2 FROM Table");
string s= dt.Rows[0][1].ToString();
But to be honest as long as you can get 0 or more then 1 results back you want to use a loop to irate through.
If you are using DataTable use:
datatable.rows[0][1].toString()
or if you are using an IEnumerable object use
objectName[0].propertyName.toString()
Here the propertyName is the name of the property you are using for that DataColumn.
From http://msdn.microsoft.com/en-us/library/webmatrix.data.database.query%28v=vs.111%29.aspx i am seeing query method returns IEnumerable objects so you may need the second way.
Thank you
I have used the following code to get one more than the biggest ID in a table using razor
#foreach (var top in db.Query("SELECT MAX(ID)+1 as ID FROM mytable"))
{
if (#top.ID == null) {#top.ID = 1; }
}
if the table is empty, #top.ID returns null. I am trying to set its value to 1 if it is null. It however shows an error in the assignment part. How do you assign the value of #top.ID to something else? Or is there a way to user the sql query to set ID as 1 if the table is empty?
You can use
select isnull(max(ID),1) from YourTable
However, if you're trying to generate a new ID for a new record, you'd be better advised to use an identity field.
I have a DataTable dt with 2 columns. First col (call it CustomerId) is unique and doesn't allow nulls. the second one allows nulls and is not unique.
From a method I get a CustomerId and then I would like to either insert a new record if this CustomerId doesn't exist or increment by 1 what's in the second column corresponding to that CustomerId if it exists.
I'm not sure how I should approach this. I wrote a select statement (which returns System.Data.DataRow) but I don't know how to test whether it returned an empty string.
Currently I have:
//I want to insert a new row
if (dt.Select("CustomerId ='" + customerId + "'") == null) //Always true :|
{
DataRow dr = dt.NewRow();
dr["CustomerId"] = customerId;
}
If the datatable is being populated by a database. I would recommend making the customerid a identity column. That way when you add a new row it will automatically create a new customerid which will be unique and 1 greater than the previous id (depending on how you setup your identity column)
I would check the row count which is returned from the select statement. Something like
I would also use string.Format...
So it would look like this
var selectStatement = string.Format("CustomerId = {0}", customerId);
var rows = dt.Select(selectStatement);
if (rows.Count < 1){
var dr = dt.NewRow();
dr["CustomerId"] = customerId;
}
This is my method to solve similar problem. You can modify it to fit your needs.
public static bool ImportRowIfNotExists(DataTable dataTable, DataRow dataRow, string keyColumnName)
{
string selectStatement = string.Format("{0} = '{1}'", keyColumnName, dataRow[keyColumnName]);
DataRow[] rows = dataTable.Select(selectStatement);
if (rows.Length == 0)
{
dataTable.ImportRow(dataRow);
return true;
}
else
{
return false;
}
}
The Select Method returns an array of DataRow objects. Just check if its length is zero (it's never null).
By the way, don't write such statements in the code directly as in this example. There's a technique for breaching your code's security called "SQL Injection", I encourage you to read the Wikipedia Article. In brief, an experienced user could write SQL script that gets executed by your database and potentially do harmful things if you're taking customerId from the user as a string. I'm not experienced in database programming, this is just "general knowledge"...