How can I use TableDirect for SQL Server CE? - c#

I have code that works for querying data from a SQL Server CE table and populating a generic list with it. That can be seen here:
But a comment there indicates I should trade in my horse-and-buggy for a Leer Jet; so, I'm trying to adapt code I found here and have this so far:
public static List<HHSUtils.InventoryItem> SelectLocalInventoryItemsTableDirect()
{
var invItems = new List<HHSUtils.InventoryItem>();
using (var conn = new SqlCeConnection(dataSource))
{
conn.Open();
SqlCeCommand cmd = conn.CreateCommand();
cmd.CommandType = CommandType.TableDirect;
cmd.CommandText = "InventoryItems";
using (SqlCeResultSet rs cmd.ExecuteResultSet(ResultSetOptions.Scrollable))
{
cmd.Prepare();
while (rs.Read())
{
var invItem = new HHSUtils.InventoryItem
{
Id = Convert.ToString(rs["Id"]),
PackSize = Convert.ToInt16(rs["PackSize"]),
Description = Convert.ToString(rs["Description"]),
DeptDotSubdept = Convert.ToDouble(rs["DeptDotSubdept"]),
Unit_Cost = Convert.ToDouble(rs["UnitCost"]),
Unit_List = Convert.ToDouble(rs["UnitList"]),
UPC_code = Convert.ToString(rs["UPCCode"]),
UPC_pack_size = Convert.ToInt16(rs["UPCPackSize"]),
CRV_Id = Convert.ToInt32(rs["CRVId"])
};
invItems.Add(invItem);
}
}
}
return invItems;
}
...but since I'm simply looping through the result set to populate the generic list, I reckon I don't want ResultSetOptions.Updatable (and I'll need different code following that). Of the following possibilities:
Insensitive
None
Scrollable
Sensitive
Updatable
...which is best for my situation - Scrollable?
UPDATE
This seems to work fine, and fast, but I still don't know which ResultSetOptions property is optimal...This msdn article talks about this enumeration, but doesn't exactly go into great depth about when they should/not be used.

You'd want to use None in your case. cmd.Prepare is also unnecessary. As indicated in this question, GetValues is also faster.

Related

SQL Query Selecting data from a specific time period

So im trying to select students, rooms and so on from a specific time period which is between 01-01-2020 and 30_06-2020. I tried googleing to see if i could find the answer but it seems tricky to just find something that will work for my instance
public static List<Student_Room> GetFirstSemesterStudents(int id)
{
List<Student_Room> studentRoomList = new List<Student_Room>();
string query = $"select Leasing.Student_No, Leasing.Room_No, Student.Name, Leasing.Date_From, Leasing.Date_To from Leasing,Student where Leasing.Date_from = '01012020' AND Leasing.Date_To = '30062020' AND Dormitory_No = #id";
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
SqlCommand command = new SqlCommand(query, connection);
command.Parameters.AddWithValue("#id", id);
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
Student_Room studentRoom = new Student_Room();
studentRoom.Student_No = Convert.ToInt32(reader["Student_No"]);
studentRoom.Student_Name = Convert.ToString(reader["Name"]);
studentRoom.Room_No = Convert.ToInt32(reader["Room_No"]);
studentRoom.Date_From = Convert.ToDateTime(reader["Date_From"]);
studentRoom.Date_To = Convert.ToDateTime(reader["Date_To"]);
studentRoomList.Add(studentRoom);
}
return studentRoomList;
}
}
}
The main problem is just that i dont know how to write the query, ther rest should be correct. i get the "Conversion failed when converting date and/or time from character string" when i try to run the function on the site
We just started learning about this stuff so im still not the best at queries and dont know much, thank for looking at it and helping appriciate it :D
make sure in database you have to define the datatype for date as the same in the Student_Room class, either date alone or datetime , if you want to chage to date alone as it is defined in the class the you can use
studentRoom.Date_From = DateTime.Parse(reader["Date_From"]);
studentRoom.Date_To = DateTime.Parse(reader["Date_To"]);

iDB2 Select command with parameters returning SQL0418

I'm developing a .NET application that connects to a DB2 iSeries 7.1 database, using the IBM.Data.DB2.iSeries.dll.
I need to do a SELECT command that has n parameters which are defined in the query as #paramX, setting the parameter values afterwards, but when I run the code I get a SQL048 Use of parameter marker not valid.. I've searched everywhere for documentation / examples but everything I've read is in par with the code I'm using. Am I missing something? If this is not valid, what is the best alternative?
This is the isolated code I'm using to test.
static void Main(string[] args)
{
String myConnectionString = "DataSource=*******;Database=*******;UserId=*******;Password=*******;";
iDB2Connection myConnection = new iDB2Connection();
try{
myConnection.ConnectionString = myConnectionString;
myConnection.Open();
var cmd = new iDB2Command("SELECT TIMESTAMP(DATE(#param0),TIME(#param1)) FROM SYSIBM.SYSDUMMY1", myConnection);
cmd.Parameters.Add(new iDB2Parameter("#param0", iDB2DbType.iDB2Char));
cmd.Parameters["#param0"].Value = "1900-01-01";
cmd.Parameters.Add(new iDB2Parameter("#param1", iDB2DbType.iDB2Char));
cmd.Parameters["#param1"].Value = "00.00.00";
using (var reader = cmd.ExecuteReader())
{
if (reader.HasRows)
{
reader.Read();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < reader.FieldCount; i++)
{
sb.AppendLine(reader[i].ToString().Trim());
}
Console.Out.WriteLine(sb.ToString());
}
}
}catch(Exception e)
{
Console.Out.WriteLine(e.ToString());
}finally{
if (myConnection != null)
{
myConnection.Close();
}
}
Console.Read();
}
EDIT
In an unrelated answer I've found that the problem might be that DB2 doesn't know the underlying type of the parameter (which is strange since I'm strong typing it), thus, a possible solution is to do a cast in the query to the expected param type, as such:
SELECT TIMESTAMP(DATE(cast(#param0 as char(10))),TIME(cast(#param1 as char(10)))) FROM SYSIBM.SYSDUMMY1
This actually worked but, isn't there any better way to handle this?
AFAIK, this is a platform limitation. that can be confirmed by an explanation that the platform adds to the application exception*. That being said, as I can't change the parameters I receive and don't have access to the info they are going to held in the query, the best solution to my specific problem is to do a CAST to the types that the TIMESTAMP scalar function uses, e.g.:
SELECT TIMESTAMP(cast(#param0 as DATE),cast(#param1 as TIME)) FROM SYSIBM.SYSDUMMY1

asp.net C# database table column to list

I have an asp.net project done in C# (my C# syntax is very rusty) and am using the built in database it creates with the project. I've created a table called aspnet_Tutorials that (for now) stores two columns of user submitted data: TutorialName and TutorialContent. Very simple, it's a learning project.
What I need to do is create a list from the first column of aspnet_Tutorials to use it to create a "directory" of the tutorials on a page. The part I'm having trouble with, mostly syntactically, is connecting to and iterating over the column to get the values into a list. Could anyone provide a straight forward example of this? And possibly explain what's going on in the code.
public class TutorialsDirDAL
{
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["ApplicationServices"].ConnectionString);
SqlCommand cmd = new SqlCommand();
SqlDataAdapter da = new SqlDataAdapter();
DataSet ds = new DataSet();
public List<string> DisplayTutorials() //parameters? String qry?
{
//query the database table, foreach loop over the data, place it into a list?
}
}
I know how to write simple sql queries. But I've seen a couple different set ups for this in my Googling spree. I currently have the following for a query, feel free to pick it apart or offer a better solution than using a query.
cmd.CommandText = "SELECT * FROM ASPNET_TUTORIALS (TutorialTitle)"
+ "VALUES (#tutorialTitle)";
Thank you!
ebad86's answer is acceptable but since you are obviously learning I think introducing OO principals muddy the water with what you are trying to learn at this point.
Here is a basic method:
private void GetData()
{
//The object that will physically connect to the database
using(SqlConnection cnx = new SqlConnection("<your connection string>")
{
//The SQL you want to execute
SqlCommand cmd = new SqlCommand("SELECT * FROM ASPNET_TUTORIALS");
//Open the connection to the database
cnx.Open();
//execute your command
using (IDataReader dataReader = cnx.ExecuteReader(cmd))
{
//Loop through your results
while(dataReader.Read())
{
//do whatever to the data
ListItem item = new ListItem(Convert.ToString(dataReader["TutorialName"]));
lst.Items.Add(item);
}
}
}
}
This is all very straightforward. The part you are most interested in is the while loop though. The loop will go through all of the returned records and you can do whatever you need to do with them. In my example I have assumed that there is a ListBox named 'lst' and I am simply adding ListItems to it that will have the name of whatever 'TutorialName' is. You can make literally do whatever you need to do with the data at this point. To fit your example (returning a List) you would do this:
private List<string> GetData()
{
List<string> lst = new List<string>();
//The object that will physically connect to the database
using(SqlConnection cnx = new SqlConnection("<your connection string>")
{
//The SQL you want to execute
SqlCommand cmd = new SqlCommand("SELECT * FROM ASPNET_TUTORIALS");
//Open the connection to the database
cnx.Open();
//execute your command
using (IDataReader dataReader = cnx.ExecuteReader(cmd))
{
//Loop through your results
while(dataReader.Read())
{
lst.Add(Convert.ToString(dataReader["TutorialName"]));
}
}
}
return lst;
}
Please respond if you have any questions.
Well you can fetch using data reader and map to the object. I can give you some rough code, which could be like this:
using (IDataReader objDataReader = objDB.ExecuteReader(objCMD))
{
while (objDataReader.Read())
{
DataBaseObject obj = new DataBaseObject();
obj = MapObjectToList(objDataReader);
ObjectList.Add(obj);
}
objDataReader.Dispose();
}
// Mapping Function can be called somewhat like this:
private DataBaseObject MapObjectToList(IDataReader objDataReader)
{
DataBaseObject obj = new DataBaseObject();
obj.Prop1Name = base.GetDataValue<string>(objDataReader, "Column1Name");
obj.Prop2Name = base.GetDataValue<string>(objDataReader, "Column2Name");
return obj;
}
But this is just a rough idea how I would do it.

Retrieve single value from Database, much like DLookup() in MS Access

I am exploring Silverlight (C#) and SQLServer as a next evolution for our current (slow) Access database. So far everything has been great, using DomainServices to retrieve the data I need. In our database we have a table (Supervisors) with Supervisor_ID, Supervisor_FirstName, Supervisor_LastName and many other fields.
What I want to do is recreate a function I use in my current database called EntityNameFirstLast(EntityID) which would take an integer. I could then retrieve the value of [Supervisor_FirstName] from [Supervisors] table where [Supervisor_ID] == EntityID using the following:
FirstName = DLookup("[Supervisor_FirstName]", "Supervisors", "[Supervisor_ID] = EntityID
I would do the same for lastname and combine the strings returning one string with First and last name.
How can I get just a single value from my database through my DomainService (or any way for that matter)? I understand that IQueryable GetSupervisorByID(Int SupID) will return the entire row that I need, but how can I get a specific field from that row?
I am also aware that I can set the DomainDataSource in my XAML and then bind to the data I want, but I am curious if what I asked above is doable or not.
There are number of ways you can accomplish your requirement if what you need is a single value from MS-SQL server:
1.Use a Query to do the concatenation and then use its output in your code
Select Supervisor_FirstName + ' ' + Supervisor_LastName as Supervisor_FullName From Supervisors Where Supervisor_ID = EntityID
Now you can get the above query to execute through a SqlCommand and get the part thats interesting to you
private string GetSupervisorFullName(string entityID, string connectionString) {
string query = "Select Supervisor_FirstName + ' ' + Supervisor_LastName as Supervisor_FullName From Supervisors Where Supervisor_ID = #EntityID";
string supervisorFullname = "";
using(SqlConnection con = new SqlConnection(connectionString)) {
SqlCommand cmdSupervisorFullname = new SqlCommand();
cmdSupervisorFullname.Connection = con;
cmdSupervisorFullname.CommandText = query;
cmdSupervisorFullname.CommandType = CommandType.Text;
SqlParameter paraEntityID = new SqlParameter();
paraEntityID.ParameterName = "#EntityID";
paraEntityID.SqlDbType = SqlDbType.NVarChar;
paraEntityID.Direction = ParameterDirection.Input;
paraEntityID.Value = entityID;
cmdSupervisorFullname.Parameters.Add(paraEntityID);
try {
con.Open();
supervisorFullname = (String) cmdSupervisorFullname.ExecuteScalar();
} catch(Exception ex) {
Console.WriteLine(ex.Message);
}
return supervisorFullname;
}
}
2.Second way would be create a Scalar function in the SQL for your requirement and then access that function using the same kind of method as mentioned above.
Then finally you would take the return value from your method GetSupervisorFullName and populate any control value of your choice.
Please do note that there are again other methods of doing the same with LINQtoSQL or with any other ORM tools. The above 2 methods are the basic way of accomplishing them.
Hope that helps.

What is best approach to get sql data from C#

I'm trying to find optimal (fast vs easiest) way to access SQL Server code thru code in C#.
As I was learning from books I've encountered multiple suggestions usually telling me to do it via drag and drop. However since I wanted to do it in code first approach was to get data by column numbers, but any reordering in SQL Query (like adding/removing columns) was pain for me to fix.
For example (don't laugh, some code is like 2 years old), I even coded special function to pass sqlQueryResult and check if it's null or not):
public static void exampleByColumnNumber(string varValue) {
string preparedCommand = #"SELECT TOP 1 [SomeColumn],[SomeColumn2]
FROM [Database].[dbo].[Table]
WHERE [SomeOtherColumn] = #varValue";
SqlCommand sqlQuery = new SqlCommand(preparedCommand, Locale.sqlDataConnection);
sqlQuery.Prepare();
sqlQuery.Parameters.AddWithValue("#varValue) ", varValue);
SqlDataReader sqlQueryResult = sqlQuery.ExecuteReader();
if (sqlQueryResult != null) {
while (sqlQueryResult.Read()) {
string var1 = Locale.checkForNullReturnString(sqlQueryResult, 0);
string var2 = Locale.checkForNullReturnString(sqlQueryResult, 1);
}
sqlQueryResult.Close();
}
}
Later on I found out it's possible thru column names (which seems easier to read with multiple columns and a lot of changing order etc):
public static void exampleByColumnNames(string varValue) {
string preparedCommand = #"SELECT TOP 1 [SomeColumn],[SomeColumn2]
FROM [Database].[dbo].[Table]
WHERE [SomeOtherColumn] = #varValue";
SqlCommand sqlQuery = new SqlCommand(preparedCommand, Locale.sqlDataConnection);
sqlQuery.Prepare();
sqlQuery.Parameters.AddWithValue("#varValue) ", varValue);
SqlDataReader sqlQueryResult = sqlQuery.ExecuteReader();
if (sqlQueryResult != null) {
while (sqlQueryResult.Read()) {
string var1 = (string) sqlQueryResult["SomeColumn"];
string var2 = (string) sqlQueryResult["SomeColumn2"];
}
sqlQueryResult.Close();
}
}
And 3rd example is by doing it by column names but using .ToString() to make sure it's not null value, or by doing If/else on the null check.
public static void exampleByColumnNamesAgain(string varValue) {
string preparedCommand = #"SELECT TOP 1 [SomeColumn],[SomeColumn2], [SomeColumn3]
FROM [Database].[dbo].[Table]
WHERE [SomeOtherColumn] = #varValue";
SqlCommand sqlQuery = new SqlCommand(preparedCommand, Locale.sqlDataConnection);
sqlQuery.Prepare();
sqlQuery.Parameters.AddWithValue("#varValue) ", varValue);
SqlDataReader sqlQueryResult = sqlQuery.ExecuteReader();
if (sqlQueryResult != null) {
while (sqlQueryResult.Read()) {
string var1 = (string) sqlQueryResult["SomeColumn"].ToString();
DateTime var2;
DateTime.TryParse(sqlQueryResult["SomeColumn2"].ToString());
int varInt = ((int) sqlQueryResult["SomeColumn3"] == null ? 0 : (int) sqlQueryResult["SomeColumn3"];
}
sqlQueryResult.Close();
}
}
Please bare in mind that I've just created this for sake of this example and there might be some typos or some slight syntax error, but the main question is which approach is best, which is the worst (I know first one is the one that I dislike the most).
I will soon have to start / rewriting some portion of my little 90k lines app which has at least those 3 examples used widely, so i would like to get best method for speed and preferably easiest to maintain (hopefully it will be same approach).
Probably there are some better options out there so please share?
It seems you may be looking at old books. If you're going to do it the "old fashioned way", then you should at least use using blocks. Summary:
using (var connection = new SqlConnection(connectionString))
{
using (var command = new SqlCommand(commandString, connection))
{
using (var reader = command.ExecuteReader())
{
// Use the reader
}
}
}
Better still, look into Entity Framework.
Links: Data Developer Center
If it's easy you're looking for, you can't do any better than Linq-to-SQL:-
http://weblogs.asp.net/scottgu/archive/2007/05/19/using-linq-to-sql-part-1.aspx
If your SQL database already exists, you can be up-and-running in seconds.
Otherwise, I agree with John.
you should have a look into these tutorials,
[http://www.asp.net/learn/data-access/][1]
All the work you are planning is already been done.
have a look at this way of doing same what you are doinng
string preparedCommand =
#"SELECT TOP 1 [SomeColumn],[SomeColumn2], [SomeColumn3]
FROM [Database].[dbo].[Table]
WHERE [SomeOtherColumn] = #varValue";
[1]: http://www.asp.net/learn/data-access/
More better way of doing the same above is by Using LINQ TO SQL
var result = from someObject in SomeTable
where SomeColumnHasValue == ValueToCompare
select new { SomeColumn, SomeColumn1, SomeColumn2};
No Type Safety Issues
Visualise Database in C# while you
work on it
at compile time less errors
less code
more productive
Following are some of the great resources for LINQ if you are interested
http://msdn.microsoft.com/en-us/vcsharp/aa336746.aspx
http://www.hookedonlinq.com/MainPage.ashx
https://stackoverflow.com/questions/47740/what-are-some-good-linq-resouces
Hope it helps
If you're looking into using just straight ADO.net you might want to go out and find Microsoft's Enterprise Library's Data Access Application Block . David Hayden has a decent article that goes into some detail about using it.
Good luck and hope this helps some.
The easiest way to do data access in C#, to my mind, is using typed DataSets. A lot of it really is drag-and-drop, and it's even easier in .NET 2.0+ than in .NET 1.0/1.1.
Have a look at this article, which talks about using typed DataSets and TableAdapters:
Building a DAL using Strongly Typed TableAdapters and DataTables in VS 2005 and ASP.NET 2.0
A typed DataSet is basically a container for your data. You use a TableAdapter to fill it (which happens with SQL or stored procs, whichever you prefer) and to update the data afterwards. The column names in each DataTables in your DataSet are autogenerated from the SQL used to fill them; and relations between database tables are mirrored by relations between DataTables in the DataSet.
Don't convert data to strings only to try to parse it; DataReaders have methods to convert SQL data to .Net data types:
using (var connection = new SqlConnection(Locale.sqlDataConnection))
using (var command = new SqlCommand(preparedCommand, connection))
using (var reader = command.ExecuteReader())
{
int stringColumnOrdinal = reader.GetOrdinal("SomeColumn");
int dateColumnOrdinal = reader.GetOrdinal("SomeColumn2");
int nullableIntColumnOrdinal = reader.GetOrdinal("SomeColumn3");
while (reader.Read())
{
string var1 = reader.GetString(stringColumnOrdinal);
DateTime var2 = reader.GetDateTime(dateColumnOrdinal);
int? var3 = reader.IsDBNull(nullableIntColumnOrdinal) ? null : (int?)reader.GetInt32(nullableIntColumnOrdinal);
}
}
I test the many different ways for get data from sql server database and i faced & found fastest way is following:
First of all create class with "IDataRecord" parameterized method as per your required properties.
class emp
{
public int empid { get; set; }
public string name { get; set; }
public static emp create(IDataRecord record)
{
return new emp
{
empid = Convert.ToInt32(record["Pk_HotelId"]),
name = record["HotelName"].ToString()
};
}
}
Now create method for get data as below:
public List<S> GetData<S>(string query, Func<IDataRecord, S> selector)
{
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = query;
cmd.Connection.Open();
using (var r = cmd.ExecuteReader())
{
var items = new List<S>();
while (r.Read())
items.Add(selector(r));
return items;
}
}
}
And then call function like:
var data = GetData<emp>("select * from employeeMaster", emp.create);

Categories

Resources