StoredProcedure Incorrect Number of Arguments (C#) - c#

I have a StoredProcedure that I created like this;
CREATE DEFINER=`mysqladmin`#`%` PROCEDURE `Alerts_GetAlerts`(IN managerID INT)
BEGIN
SELECT ID, Type, EmpID, ManagerID, HolID
FROM Alerts
WHERE ManagerID = managerID;
END$$
I then try to call this from my C# code like so;
using (var con = new MySqlConnection(MySQLConStr))
{
con.Open();
using (MySqlCommand cmd = new MySqlCommand("Alerts_GetAlerts", con))
{
cmd.Parameters.AddWithValue("#managerID", managerID);
using (var dataReader = cmd.ExecuteReader())
{
while (dataReader.Read())
{
var alert = new AlertsModel
{
ID = Convert.ToInt32(dataReader[0]),
Type = Convert.ToInt32(dataReader[1]),
ManagerID = Convert.ToInt32(dataReader[2]),
EmployeeID = Convert.ToInt32(dataReader[3]),
HolidayID = Convert.ToInt32(dataReader[4]),
};
AllAlerts.Add(alert);
}
}
}
return AllAlerts;
}
However I constantly get, Incorrect number of arguments for PROCEDURE sdcdatabase.Alerts_GetAlerts; expected 1, got 0 even though to me it appears I am passing the managerID argument through;
cmd.Parameters.AddWithValue("#managerID", managerID);
Where am I going wrong?

try this code
using (var con = new MySqlConnection(MySQLConStr))
{
con.Open();
using (MySqlCommand cmd = new MySqlCommand("Alerts_GetAlerts(#managerID)", con))
{
cmd.Parameters.AddWithValue("#managerID", managerID);
using (var dataReader = cmd.ExecuteReader())
{
while (dataReader.Read())
{
var alert = new AlertsModel
{
ID = Convert.ToInt32(dataReader[0]),
Type = Convert.ToInt32(dataReader[1]),
ManagerID = Convert.ToInt32(dataReader[2]),
EmployeeID = Convert.ToInt32(dataReader[3]),
HolidayID = Convert.ToInt32(dataReader[4]),
};
AllAlerts.Add(alert);
}
}
}
return AllAlerts;
}

Related

How to return results from SQL SELECT raw Query?

I have a method in my controller class that is supposed to return the results from a raw SQL query inside the method. The problem is I can't pull return more than one column result to the list in a query that is supposed to return multiple column results.
I know that the problem has to do with how I am adding to the results list during the Read, but I am unsure how to structure this properly to return multiple values.
Here is my current method:
public IActionResult Search ([FromRoute]string input)
{
string sqlcon = _iconfiguration.GetSection("ConnectionStrings").GetSection("StringName").Value;
List<string> results = new List<string>();
using (var con = new SqlConnection(sqlcon))
{
using (var cmd = new SqlCommand()
{
CommandText = "SELECT u.UserID, u.User FROM [dbo].[Users] u WHERE User = 'Value';",
CommandType = CommandType.Text,
Connection = con
})
{
con.Open();
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
results.Add(reader.GetString(0));
}
con.Close();
return Ok(new Search(results));
}
}
}
}
The SQL query is supposed to return the UserID and User based on the entered User, however, only the User gets returned here.
Does anyone know what I am missing to return multiple column names for this SQL query and method? Any advice would be greatly appreciated.
FYI, I can't use a stored procedure here, I do not have permission to create an SP on this database.
You can create a class for the results of the Query
public class ClassForResults(){
public int UserID { get; set; };
public string User { get; set; }
}
public IActionResult Search ([FromRoute]string input)
{
string sqlcon = _iconfiguration.GetSection("ConnectionStrings").GetSection("StringName").Value;
List<ClassForResults> results = new List<ClassForResults>();
using (var con = new SqlConnection(sqlcon))
{
using (var cmd = new SqlCommand()
{
CommandText = "SELECT u.UserID, u.User FROM [dbo].[Users] u WHERE User = 'Value';",
CommandType = CommandType.Text,
Connection = con
})
{
con.Open();
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
ClassForResults result = new ClassForResults();
result.UserID = reader.GetInt(0);
result.User = reader.GetString(1);
results.Add(result);
}
con.Close();
return Ok(new Search(results));
}
}
}
}

C# ExecuteReader fails if condition

Why only the else condition runs? Postalcode column is float, City column is nvarchar. I think the fail is the string may be mistake.
private void txt_st_postalcode_Leave(object sender, EventArgs e)
{
using (var connection = new SqlConnection("Data Source=mypublicip\\SQLEXPRESS2017;Initial Catalog=studentreg; User = myusername; Password=mypassword;"))
{
connection.Open();
using (var command = new SqlCommand("SELECT City FROM Cities WHERE Postcode=#Postcode", connection))
{
command.Parameters.AddWithValue("#Postcode", "10101");
using (var reader = command.ExecuteReader())
{
string txt_st_postalcode = reader.Read() ?
reader[1] as string : ("City");
if (reader.Read())
{
txt_st_city.Text = reader.GetString(reader.GetOrdinal("City"));
}
else
{
MessageBox.Show("Sh*t!");
}
}
}
}
}
Not too sure how these postcodes work (different in the UK), but given that you're using ExecuteReader you appear to be expecting multiple results. As the comments have pointed out, you're currently reading the results twice; however, you should probably have some form of loop; for example:
using (var command = new SqlCommand("SELECT City FROM Cities WHERE Postcode=#Postcode", connection))
{
command.Parameters.AddWithValue("#Postcode", "10101");
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
string txt_st_postalcode = reader[0] as string;
//txt_st_city.Text = reader.GetString(reader.GetOrdinal("City"));
// Depends what you're doing here?
}
}
}
If you only expect a single result, try using ExecuteScalar() which will return a single result; for example:
using (var command = new SqlCommand("SELECT City FROM Cities WHERE Postcode=#Postcode", connection))
{
command.Parameters.AddWithValue("#Postcode", "10101");
txt_st_city.Text = command.ExecuteScalar();
}
Firstly, if you need to read PostCode from the reader, you have to select first. So, change your query.
using (var command = new SqlCommand("SELECT City, PostCode FROM Cities WHERE Postcode=#Postcode", connection))
Secondly, calling read once per row before getting data.
if (reader.Read())
{
txt_st_postalcode .Text = reader.GetString(reader.GetOrdinal("PostCode"));
txt_st_city.Text = reader.GetString(reader.GetOrdinal("City"));
}
else
{
MessageBox.Show("Sh*t!");
}

Using IEnumerable<IDataRecord> to return data

I am trying to return data using IEnumerable with given fields, where I am calling the the method I want to reference the data with given field name and return that.
Example, here is the function
public IEnumerable<IDataRecord> GetSomeData(string fields, string table, string where = null, int count = 0)
{
string sql = "SELECT #Fields FROM #Table WHERE #Where";
using (SqlConnection cn = new SqlConnection(db.getDBstring(Globals.booDebug)))
using (SqlCommand cmd = new SqlCommand(sql, cn))
{
cmd.Parameters.Add("#Fields", SqlDbType.NVarChar, 255).Value = where;
cn.Open();
using (IDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
yield return (IDataRecord)rdr;
}
}
}
}
Calling:
IEnumerable<IDataRecord> data = bw.GetSomeData("StaffCode, Perms", "BW_Staff", "StaffCode = 'KAA'");
What must I do to return the data this way or what way ?
string staffCode = data["StaffCode"].ToString();
string perms = data["Perms"].ToString();
Thanks for any help
your data variable is a collection of rows. You need to iterate over the collection to do something interesting with each row.
foreach (var row in data)
{
string staffCode = row["StaffCode"].ToString();
string perms = row["Perms"].ToString();
}
Update:
Based on your comment that you only expect GetSomeData(...) to return a single row, I'd suggest 1 of two things.
Change the signature of GetSomeData to return an IDataRecord. and remove "yield" from the implementation.
public IDataRecord GetSomeData(string fields, string table, string where = null, int count = 0)
{
string sql = "SELECT #Fields FROM #Table WHERE #Where";
using (SqlConnection cn = new SqlConnection(db.getDBstring(Globals.booDebug)))
using (SqlCommand cmd = new SqlCommand(sql, cn))
{
cmd.Parameters.Add("#Fields", SqlDbType.NVarChar, 255).Value = where;
cn.Open();
using (IDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
return (IDataRecord)rdr;
}
}
}
}
}
Or
var row = data.FirstOrDefault();
if (row != null)
{
string staffCode = row["StaffCode"].ToString();
string perms = row["Perms"].ToString();
}
Remarks:
Your implementation of GetSomeData is incomplete. You are not even using several of the parameters, most importantly the fields parameter. And conceptually in SQL you can't parameterize which fields get returned or which table gets used (etc.), but rather you need to construct a dynamic query and execute it.
Update 2
Here is an implementation of GetSomeData that constructs a proper query (in C# 6, let me know if you need it in an earlier version).
public IEnumerable<IDataRecord> GetSomeData(IEnumerable<string> fields, string table, string where = null, int count = 0)
{
var predicate = string.IsNullOrWhiteSpace(where) ? "" : " WHERE " + where;
string sql = $"SELECT { string.Join(",", fields) } FROM {table} {predicate}";
using (SqlConnection cn = new SqlConnection(db.getDBstring(Globals.booDebug)))
using (SqlCommand cmd = new SqlCommand(sql, cn))
{
cn.Open();
using (IDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
yield return (IDataRecord)rdr;
}
}
}
}
And here is how you would use it.
IEnumerable<IDataRecord> data = bw.GetSomeData(new[] { "StaffCode", "Perms" }, "BW_Staff", "StaffCode = 'KAA'");
You can either enumerate it or call .FirstOrDefault, it's your choice. Each time you call GetSomeData, it will run the query.
Update 3
GetSomeData implemented with earlier versions of C#
public IEnumerable<IDataRecord> GetSomeData(IEnumerable<string> fields, string table, string where = null, int count = 0)
{
var predicate = string.IsNullOrEmpty(where) ? "" : " WHERE " + where;
string sql = string.Format("SELECT {0} FROM {1} {2}", string.Join(",", fields), table, predicate);
using (SqlConnection cn = new SqlConnection(db.getDBstring(Globals.booDebug)))
using (SqlCommand cmd = new SqlCommand(sql, cn))
{
cn.Open();
using (IDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
yield return (IDataRecord)rdr;
}
}
}
}

ADO.NET ExecuteReader Returns No Results

I'm updating some old legacy code and I ran into a problem with the
SqlCommand.ExecuteReader() method. The problem is that it's not returning any
results. However, using SqlDataAdapter.Fill(), I get results back from the
database. What am I doing wrong? How can I get results back using the data
reader?
var connectionString = ConfigurationManager.ConnectionStrings["MyConnectionString"].ToString();
using (var sqlConnection = new SqlConnection(connectionString))
{
using (var sqlCommand = new SqlCommand())
{
sqlCommand.Connection = sqlConnection;
sqlCommand.CommandType = CommandType.Text;
sqlCommand.CommandText = "SELECT * FROM MyTable WHERE ID = 1";
sqlConnection.Open();
// This code works.
//var dataTable = new DataTable();
//using (var sqlDataAdapter = new SqlDataAdapter(sqlCommand))
//{
// sqlDataAdapter.Fill(dataTable);
//}
// This code is not working.
using (var sqlDataReader = sqlCommand.ExecuteReader())
{
while (sqlDataReader.Read())
{
// This fails because the data reader has no results.
var id = sqlDataReader.GetInt32(0);
}
}
}
}
Could it be that there is no Int32 in your results ?
var id = sqlDataReader.GetInt32(0); // <-- this might not be an Int32
Either try:
var id = sqlDataReader.GetValue(0);
Or cast to the correct type (BIGINT for example is Int64), not sure without seeing your data.
Try this..
var id = 0;
using (var sqlDataReader = sqlCommand.ExecuteReader())
{
while (sqlDataReader.Read())
{
id = sqlDataReader.GetInt32(sqlDataReader.GetOrdinal("ColName"));
}
}
I have moved the variable outside of the reader code or the variable will only be accessible inside that scope. I would avoid specifying the ordinal in the code, in case someone altered the columns in the DB.
Also, specify the columns in the SQL statement... SELECT ColName FROM ... and use params in the query
If you got to that line then it has results
Does not mean the value is not null
And you should not use a SELECT *
If may have a problem with an implicit cast
Try Int32
try
{
if(sqlDataReader.IsDBNull(0))
{
// deal with null
}
else
{
Int32 id = sqlDataReader.GetInt32(0);
}
}
catch (SQLexception Ex)
{
Debug.WriteLine(Ex.message);
}
var connectionString = ConfigurationManager.ConnectionStrings["MyConnectionString"].ToString();
using (var sqlConnection = new SqlConnection(connectionString))
{
sqlConnection.Open();
string sql = "SELECT * FROM MyTable WHERE ID = 1";
using (var sqlCommand = new SqlCommand(sql, sqlConnection))
{
using (var sqlDataReader = sqlCommand.ExecuteReader())
{
while (sqlDataReader.Read())
{
// This fails because the data reader has no results.
var id = sqlDataReader.GetInt32(0);
}
}
}
}

Is this the right way to query a SQL Server CE table for a record, populating and returning a custom object?

The code below works, but I'm wondering if it's more loquacious than necessary:
public static InventoryItem SelectLocalInventoryItem(string ID)
{
const int ID_COL = 0;
const int PACKSIZE_COL = 1;
const int DESCRIPTION_COL = 2;
const int DEPTDOTSUBDEPT_COL = 3;
const int UNITCOST_COL = 4;
const int UNITLIST_COL = 5;
const int UPCCODE_COL = 6;
const int UPCPACKSIZE_COL = 7;
const int CRVID_COL = 8;
var invItem = new InventoryItem();
using (var conn = new SqlCeConnection(dataSource))
{
var cmd = conn.CreateCommand();
cmd.CommandText = "SELECT * FROM InventoryItems WHERE Id = #IDVal";
var IDParam = cmd.CreateParameter();
IDParam.ParameterName = "#IdVal";
IDParam.Value = ID;
cmd.Parameters.Add(IDParam);
conn.Open();
cmd.Prepare();
using (var reader = cmd.ExecuteReader())
{
if (reader.Read())
{
invItem.Id = reader.GetString(ID_COL);
invItem.PackSize = reader.GetInt16(PACKSIZE_COL);
invItem.Description = reader.GetString(DESCRIPTION_COL);
invItem.DeptDotSubdept = reader.GetDouble(DEPTDOTSUBDEPT_COL);
invItem.Unit_Cost = reader.GetDouble(UNITCOST_COL);
invItem.Unit_List = reader.GetDouble(UNITLIST_COL);
invItem.UPC_code = reader.GetString(UPCCODE_COL);
invItem.UPC_pack_size = reader.GetInt16(UPCPACKSIZE_COL);
invItem.CRV_Id = reader.GetInt32(CRVID_COL);
}
}
conn.Close();
cmd.Dispose();
return invItem;
}
}
The table being queried is created like so:
using (var connection = new SqlCeConnection(dataSource))
{
connection.Open();
using (var command = new SqlCeCommand())
{
command.Connection = connection;
if (TableExists(connection, "InventoryItems"))
{
command.CommandText = "DROP TABLE InventoryItems";
command.ExecuteNonQuery();
}
command.CommandText = "CREATE TABLE InventoryItems (Id nvarchar(50) NOT
NULL, PackSize smallint NOT NULL, Description nvarchar(255),
DeptDotSubdept float, UnitCost float, UnitList float, UPCCode
nvarchar(50), UPCPackSize smallint, CRVId int);";
command.ExecuteNonQuery();
. . .
}
}
The class is declared thusly:
public class InventoryItem
{
public string Id { get; set; }
public int PackSize { get; set; }
public string Description { get; set; }
public double DeptDotSubdept { get; set; }
public double Unit_Cost { get; set; }
public double Unit_List { get; set; }
public string UPC_code { get; set; }
public int UPC_pack_size { get; set; }
public int CRV_Id { get; set; }
}
Is there an easier/quicker way to accomplish this, or do I really have to painstakingly manually assign each returned column to each class member?
UPDATE
I implemented Sergey K's suggestions, and here it is now:
public static InventoryItem SelectLocalInventoryItem(string ID)
{
InventoryItem invItem = null;
using (var conn = new SqlCeConnection(dataSource))
{
var cmd = conn.CreateCommand();
cmd.CommandText = "SELECT * FROM InventoryItems WHERE Id = #IDVal";
var IDParam = cmd.CreateParameter();
IDParam.ParameterName = "#IdVal";
IDParam.Value = ID;
cmd.Parameters.Add(IDParam);
conn.Open();
cmd.Prepare();
using (var reader = cmd.ExecuteReader())
{
if (reader.Read())
{
invItem = new InventoryItem
{
Id = Convert.ToString(reader["Id"]),
PackSize = Convert.ToInt16(reader["PackSize"]),
Description = Convert.ToString(reader["Description"]),
DeptDotSubdept = Convert.ToDouble(reader["DeptDotSubdept"]),
Unit_Cost = Convert.ToDouble(reader["UnitCost"]),
Unit_List = Convert.ToDouble(reader["UnitList"]),
UPC_code = Convert.ToString(reader["UPCCode"]),
UPC_pack_size = Convert.ToInt16(reader["UPCPackSize"]),
CRV_Id = Convert.ToInt32(reader["CRVId"])
};
}
}
return invItem;
}
}
UPDATE 2
For the record/posterity, here is a related method that returns all the values, rather than a single "record"/class instance:
public static List<InventoryItem> SelectLocalInventoryItems()
{
List<InventoryItem> invItems = new List<InventoryItem>();
using (var conn = new SqlCeConnection(dataSource))
{
var cmd = conn.CreateCommand();
cmd.CommandText = "SELECT * FROM InventoryItems";
conn.Open();
cmd.Prepare();
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
var invItem = new InventoryItem
{
Id = Convert.ToString(reader["Id"]),
PackSize = Convert.ToInt16(reader["PackSize"]),
Description = Convert.ToString(reader["Description"]),
DeptDotSubdept = Convert.ToDouble(reader["DeptDotSubdept"]),
Unit_Cost = Convert.ToDouble(reader["UnitCost"]),
Unit_List = Convert.ToDouble(reader["UnitList"]),
UPC_code = Convert.ToString(reader["UPCCode"]),
UPC_pack_size = Convert.ToInt16(reader["UPCPackSize"]),
CRV_Id = Convert.ToInt32(reader["CRVId"])
};
invItems.Add(invItem);
}
}
}
return invItems;
}
UPDATE 3
This is an update of update 2, following ctacke's suggestion:
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;
}
I don't know yet if ResultSetOptions.Scrollable is the best property to use here, though... This msdn article makes me only slightly wiser.
UPDATE 4
The TableDirect change seems to be good; so I tried to implement the GetValues suggestion, too. But changing this code:
using (SqlCeResultSet rs = cmd.ExecuteResultSet(ResultSetOptions.Scrollable))
{
cmd.Prepare();
while (rs.GetValues())
{
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);
}
}
}
...to this:
using (SqlCeResultSet rs = cmd.ExecuteResultSet(ResultSetOptions.Scrollable))
{
cmd.Prepare();
Object[] values = new Object[rs.FieldCount];
int fieldCount = rs.GetValues(values);
for (int i = 0; i < fieldCount; i++)
{
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);
}
}
}
...fails on the "int fieldCount = rs.GetValues(values);" line, with "No data exists for the row/column"
UPDATE 5
In response to ctacke: So it's simply a matter of adding "Object[] values = new Object[rs.FieldCount];" before the while and "rs.GetValues(values);" after it, like so:
using (SqlCeResultSet rs = cmd.ExecuteResultSet(ResultSetOptions.Scrollable))
{
cmd.Prepare();
Object[] values = new Object[rs.FieldCount];
while (rs.Read())
{
rs.GetValues(values);
var invItem = new HHSUtils.InventoryItem
{
. . .
? It seems to work...
UPDATE 6
For posterity, this seems to be good form and work well for a "Select *" on a SQL Server CE table:
public static List<HHSUtils.Department> SelectLocalDepartments()
{
var departments = new List<HHSUtils.Department>();
using (var conn = new SqlCeConnection(dataSource))
{
conn.Open();
SqlCeCommand cmd = conn.CreateCommand();
cmd.CommandType = CommandType.TableDirect;
cmd.CommandText = "Departments";
using (SqlCeResultSet rs = cmd.ExecuteResultSet(ResultSetOptions.None))
{
var values = new Object[rs.FieldCount];
while(rs.Read())
{
rs.GetValues(values);
var dept = new HHSUtils.Department
{
Id = Convert.ToInt16(rs["Id"]),
DeptNumber = Convert.ToInt16(rs["DeptNum"]),
DeptName = Convert.ToString(rs["DepartmentName"]),
};
departments.Add(dept);
}
}
}
return departments;
}
I see few things you can do better.
Why not to use column name to get a value from reader? Something like
Convert.ToDouble(reader["DeptDotSubdept"]);
I don't see any sense to have constants to identify the column number in scope of your method.
You can use object initializer to instantiate your object.
if (reader.Read())
{
invItem = new InventoryItem{
Id = Convert.ToString(reader["Id"]),
.....
};
}
Return null reference if record is not found.
If you know what is using do, you might don't want to add this lines
conn.Close();
cmd.Dispose();
It's worth noting that if you're doing this across a lot of rows, this can be improved for speed greatly. There are two improvement paths:
Modest improvement can be made by first caching the numeric field ordinals before iterating the rows, using reader.GetValues to pull the entire data row, then accessing the resulting array with the cached ordinals.
The reason this is better is twofold. First, it skips the need for the reader to always look up the ordinal based on the name you provided, and two it doesn't require a roundtrip to the data for each field you want.
An order of magnitude improvement can be had by just opening the table using TableDirect instead of a SQL query and then doing the suggestions in #1.
EDIT
Something along these lines:
using (var rs = cmd.ExecuteResultSet())
{
var fieldCount = rs.fieldCount;
var values = new Object[rs.FieldCount];
// cache your ordinals here using rs.GetOrdinal(fieldname)
var ID_ORDINAL = rs.GetOrdinal("Id");
// etc
while(rs.Read())
{
rs.GetValues(values);
var invItem = new HHSUtils.InventoryItem
{
Id = (string)values[ID_ORDINAL],
PackSize = (short)values[PACK_SIZE_ORDINAL],
// etc
};
invItems.Add(invItem);
}
}
EDIT 2
It's probably worth noting that if you were using something like the OpenNETCF ORM, the code to do the above would look like this:
invItems = store.Select<InventoryItem>();
That's it, just one line. And it would have used TableDirect by default.

Categories