I want to set value to a literal control using LINQ. I got the result from database in var by the following code:
var result=md.StoredProc_Name(id);
Now I want to assign particular columns value to a literal. As we can do simply in asp.net as bellow with the help of datatable,
dt=obj.Test(id);
ltrlName.Text=dt.Rows[0]["Name"].ToString();
ltrlAddress.Text=dt.Rows[0]["Address"].ToString();
How can we do the same thing in LINQ?
var first = result.FirstOrDefault();
if (first != null)
{
ltrlName.Text = first.Name;
ltrlAddress.Text = first.Address;
}
Addendum - How to do this without linq to objects:
With the code below in a class called DB
var result = DB.SelectIntoItem("StoredProc_Name",
connectionString,
System.Data.CommandType.StoredProcedure,
new { param1 = "val1" });
if (!reader.Empty)
{
ltrlName.Text=result.Name;
ltrlAddress.Text=result.Address;
}
etc.
Code
public static dynamic SelectIntoItem(string SQLselect, string connectionString, CommandType cType = CommandType.Text, object parms = null)
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
using (SqlCommand cmd = conn.CreateCommand())
{
dynamic result = new System.Dynamic.ExpandoObject();
cmd.CommandType = cType;
cmd.CommandText = SQLselect;
if (parms != null)
Addparms(cmd, parms);
conn.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader.Read()) // read the first one to get the columns collection
{
var cols = reader.GetSchemaTable()
.Rows
.OfType<DataRow>()
.Select(r => r["ColumnName"]);
foreach (string col in cols)
{
((IDictionary<System.String, System.Object>)result)[col] = reader[col];
}
result.Empty = false;
if (reader.Read())
{
// error, what to do?
result.Error = true;
result.ErrorMessage = "More than one row in result set.";
}
else
{
result.Error = false;
}
}
else
{
result.Empty = true;
result.Error = false;
}
}
conn.Close();
return result;
}
}
}
private static void Addparms(SqlCommand cmd, object parms)
{
// parameter objects take the form new { propname : "value", ... }
foreach (PropertyInfo prop in parms.GetType().GetProperties())
{
cmd.Parameters.AddWithValue("#" + prop.Name, prop.GetValue(parms, null));
}
}
If you are insterested follow my GitHub, I'll be making the rest of it public soon (GitHub)
Related
I'm trying to insert some values into the database using reflection. Here is my code, query works well, but how to pass values? I don't know what went wrong:
public class MyORM<T> where T : IData
{
public void Insert(T item)
{
var sql = new StringBuilder("Insert into ");
var type = item.GetType();
var properties = type.GetProperties();
sql.Append(type.Name);
sql.Append(" (");
foreach (var property in properties)
{
sql.Append(property.Name);
sql.Append(", ");
}
sql.Remove(sql.Length - 1, 1);
sql.Append(") values (");
foreach (var property in properties)
{
sql.Append('#').Append(property.Name).Append(',');
}
sql.Remove(sql.Length - 1, 1);
sql.Append(");");
var query = sql.ToString();
var command = new SqlCommand(query, _sqlConnection);
foreach (var property in properties)
{
command.Parameters.Add(property.Name);
}
}
}
command.Parameters.AddWithValue(property.Name, property.GetValue(item));
This line will solve your problem and will be able to pass the value.
public void DBInsertNewRecordIntoTable(DatabaseTableObject databaseTableObject, string tableName)
{
string connectMe = "Server=localhost;User ID=root;Database=test";
string sqlCommand = string.Concat("SELECT * FROM ", tableName, " LIMIT 0;");
//1. Get an instance of MySqlAdapter
MySqlDataAdapter mySqlDataAdapter = new MySqlDataAdapter(sqlCommand, connectMe);
//2. Retrieve schema from tableName and store it in DataSet
DataSet dataSet = new DataSet(string.Concat(tableName, "DataSet"));
mySqlDataAdapter.FillSchema(dataSet, SchemaType.Source, tableName);
//5. Get dataTable from dataSet
DataTable dataTable = dataSet.Tables[tableName];
//6. Add new row data
DataRow dataRow = dataTable.NewRow();
//6.1 Get a list of the properties in the databaseTableObject and store it into an array
PropertyInfo[] properties = databaseTableObject.GetType().GetProperties();
//6.2 Loop through all properties in databaseTableObject and assign their values to dataRow accordingly
foreach (var property in properties)
{ //6.3 Getting property value
var propertyValue = databaseTableObject.GetType().GetProperty(property.Name).GetValue(databaseTableObject, null);
//6.4 Only assign value to dataRow if databaseTableObject's property's value is not null
if (propertyValue != null)
dataRow[property.Name] = propertyValue;
}
//7. Add dataRow data to local table
dataTable.Rows.Add(dataRow);
//8. Apply the change to remote table
_ = new MySqlCommandBuilder(mySqlDataAdapter);
mySqlDataAdapter.Update(dataSet, tableName);
Console.WriteLine("Successfully updated the remote table");
}
interface DatabaseTableObject { }
public class DatabaseTableObjectEmployee: DatabaseTableObject
{
private string name;
private int? age = null;
private int? salary = null;
public int? Age { get => age; set => age = value; }
public int? Salary { get => salary; set => salary = value; }
public string Name { get => name; set => name = value; }
}
You can add property.GetValue(entity) in your iteration to get value and store it in a dictionary to pass it and use it as a parameter.Here my code.I have implemented it.Hope this will help.
public void Insert(TEntity entity)
{
if (entity == null) return;
Type type = entity.GetType();
PropertyInfo[] propertyInfos = type.GetProperties(); `
string s1 = "", s2 = "";
bool flag = false;
`Dictionary<string, object> dic = new Dictionary<string, object>();`
foreach (var property in propertyInfos)
{
Type type1 = property .GetType();
if (!flag)
flag = true;
else {
s1 += ",";
s2 += ",";
}
s1 += property .Name;
s2 += "#" + property .Name;
dic.Add(property .Name, property.GetValue(entity));//Here getting value
} `
`string sql = "Insert into " + type.Name + " (" + s1 + ") Values (" + s2 + ");";`
` ExecuteCommand(sql, dic);`
}```
//`Database Execution portion`
`public void ExecuteCommand(string command, Dictionary<string, object> parameters)`
{
using(SqlConnection connection = new SqlConnection(_conncectionstring))
{
using(SqlCommand sqlcommand = new SqlCommand(command, connection))
{
try
{
if (connection.State != ConnectionState.Open)
{
connection.Open();
}
if (parameters != null)
{
foreach (var item in parameters)
{
sqlcommand.Parameters.Add(new SqlParameter(item.Key, item.Value));
}
}
sqlcommand.ExecuteNonQuery();
}
catch (Exception ex) {
}
}
}
}`
I have a mssql-context-class for easy access to the database. It contains a function for inserting datarows, that looks like this:
public int? Insert(string tableName, Action<SqlParameterCollection> actionSqlParameterCollection)
{
using (var sqlConnection = new SqlConnection(ConnectionString))
{
sqlConnection.Open();
using (var sqlCommand = sqlConnection.CreateCommand())
{
var commandText = $"insert into {tableName} (#columns) output inserted.id values (#values)";
var valueBuilder = new StringBuilder();
var columnBuilder = new StringBuilder();
actionSqlParameterCollection?.Invoke(sqlCommand.Parameters); //Fill the parameters from outside with some values
foreach (SqlParameter parameter in sqlCommand.Parameters)
{
valueBuilder.Append($",#{parameter.ParameterName}");
columnBuilder.Append($",{parameter.ParameterName}");
}
commandText = commandText.Replace("#values", valueBuilder.ToString().Substring(1));
commandText = commandText.Replace("#columns", columnBuilder.ToString().Substring(1));
sqlCommand.CommandText = commandText;
object result = sqlCommand.ExecuteScalar();
return (int?)result;
}
}
}
Calling this would look something like this:
var context = MsSqlContext.CreateFrom("some_connectionstring");
context.Insert("myTable", parameters => {
parameters.AddWithValue("foo_1", "bar_1");
parameters.AddWithValue("foo_2", "bar_2");
});
Now i want to build a generic sql-context-class which can also handle mysql-databases. The insert-function looks like this so far:
public int? Insert(string tableName, Action<IDataParameterCollection> actionParameterCollection)
{
using (var connection = this.CreateConnection())
{
using (var command = connection.CreateCommand())
{
var commandText = $"insert into {tableName} (#field) values (#values)";
var valueBuilder = new StringBuilder();
var columnBuilder = new StringBuilder();
actionParameterCollection?.Invoke(command.Parameters);
foreach (IDbDataParameter parameter in command.Parameters)
{
valueBuilder.Append($",#{parameter.ParameterName}");
columnBuilder.Append($",{parameter.ParameterName}");
}
commandText = commandText.Replace("#values", valueBuilder.ToString().Substring(1));
commandText = commandText.Replace("#columns", columnBuilder.ToString().Substring(1));
command.CommandText = commandText;
object result = command.ExecuteScalar();
return (int?)result;
}
}
}
When i try to call the function it looks like this:
var context = SqlContext.CreateFrom(SqlProvider.MySql, "Server=localhost;Database=4713_demo;Uid=root;Pwd=;");
context.Insert("my_table", parameters =>
{
parameters.Add(?); //It expects an object
});
My Problem is, dont want to do something like
context.Insert("my_table", parameters =>
{
parameters.Add(context.CreateParameter("foo","bar"));
});
I just want to pass the parametername and the parametervalue. the context-class itself is aware of its provider and should create the parameter. How to afford that?
The solution i came up with, is this SqlParameterizer-class.
public class SqlParameterizer
{
private SqlProvider Provider { get; set; }
private List<IDbDataParameter> ParameterList { get; set; }
public SqlParameterizer(SqlProvider sqlProvider)
{
this.Provider = sqlProvider;
this.ParameterList = new List<IDbDataParameter>();
}
public void Add(string parameterName, object parameterValue)
{
switch(this.Provider)
{
case SqlProvider.MsSql:
this.ParameterList.Add(new SqlParameter(parameterName, parameterValue));
break;
case SqlProvider.MySql:
this.ParameterList.Add(new MySqlParameter(parameterName, parameterValue));
break;
case SqlProvider.OracleSql:
throw new Exception($"SqlProvider '{this.Provider}' not supported yet...");
default:
throw new Exception($"Unknown SqlProvider '{this.Provider}'");
}
}
public IDbDataParameter[] GetParameters()
{
return ParameterList.ToArray();
}
}
Using this class will look like this:
var commandText = $"insert into {tableName} (#columns) values (#values)";
var valueBuilder = new StringBuilder();
var columnBuilder = new StringBuilder();
var parameterizer = new SqlParameterizer(this.Provider);
actionValueParameterizer?.Invoke(parameterizer);
foreach(IDbDataParameter parameter in parameterizer.GetParameters())
{
command.Parameters.Add(parameter);
valueBuilder.Append($",#{parameter.ParameterName}");
columnBuilder.Append($",{parameter.ParameterName}");
}
commandText = commandText.Replace("#values", valueBuilder.ToString().Substring(1));
commandText = commandText.Replace("#columns", columnBuilder.ToString().Substring(1));
command.CommandText = commandText;
command.ExecuteNonQuery();
Calling my insert-function:
context.Insert("some_table", parameterizer =>
{
parameterizer.Add("some_column", "some_value");
});
I have an overload:
public DataTable ExecuteStoredProcedure(string storedProcedure)
{
var dataTable = new DataTable();
using (var odbcConnection = _connection)
{
using (var odbcCommand = odbcConnection.CreateCommand())
{
odbcCommand.CommandText = storedProcedure;
odbcCommand.CommandType = CommandType.StoredProcedure;
using (var adapter = new OdbcDataAdapter(odbcCommand))
{
adapter.Fill(dataTable);
}
}
}
return dataTable;
}
and another overload:
public DataTable ExecuteStoredProcedure(string storedProcedure, List<StoredProcedureParameters> storedProcedureParameters)
{
var dataTable = new DataTable();
using (var odbcConnection = _connection)
{
using (var odbcCommand = odbcConnection.CreateCommand())
{
odbcCommand.CommandText = storedProcedure;
foreach (var parameter in storedProcedureParameters)
{
odbcCommand.Parameters.Add("#" + parameter.ParameterName, parameter.ParameterType,
parameter.LengthOfParameter).Value = parameter.ParameterName;
}
odbcCommand.CommandType = CommandType.StoredProcedure;
using (var adapter = new OdbcDataAdapter(odbcCommand))
{
adapter.Fill(dataTable);
}
}
}
return dataTable;
}
Whose contents are very similar. So similar in fact, the only difference is this line here:
foreach (var parameter in storedProcedureParameters)
{
odbcCommand.Parameters.Add("#" + parameter.ParameterName, parameter.ParameterType,
parameter.LengthOfParameter).Value = parameter.ParameterName;
}
I have spent a few hours trying to refactor this guy because they are so similar. I have tried delegates, but it made the code more unreadable. I cannot combine the functionality of the two overloads because the other overloads logic occurs in the middle of the other. Does anyone have any ideas as to how to refactor this into one readable method?
Couple of things you could do:
You could always just use the one method, but with an optional List<StoredProcedureParameters>.
Like this: (I've renamed it to spParams for brevity)
public DataTable ExecuteStoredProcedure(string storedProcedure,
List<StoredProcedureParameters> spParams
= new List<StoredProcedureParameters>())
{
var dataTable = new DataTable();
using (var odbcConnection = _connection)
{
using (var odbcCommand = odbcConnection.CreateCommand())
{
odbcCommand.CommandText = storedProcedure;
foreach (var parameter in spParams)
{
odbcCommand.Parameters.Add("#" + parameter.ParameterName, parameter.ParameterType,
parameter.LengthOfParameter).Value = parameter.ParameterName;
}
odbcCommand.CommandType = CommandType.StoredProcedure;
using (var adapter = new OdbcDataAdapter(odbcCommand))
{
adapter.Fill(dataTable);
}
}
}
return dataTable;
}
This way, you can call the same method, and choose whether to pass in the List<StoredProcedureParameters> (or not).
Using the parameter with default value of spParams= new List<StoredProcedureParameters>() will mean that any existing code calling the original 1 parameter signature will still work, saving time on extra refactoring.
Plus, it means your existing foreach block will just iterate over an empty list.
OR
You could do similar as the above, just have the spParams value be null as default, and then do a null check, like this:
public DataTable ExecuteStoredProcedure(string storedProcedure,
List<StoredProcedureParameters> spParams = null)
{
//...
if (spParams != null) // Check if the spParams is null
{
foreach(var param in spParams)
{
// Loop in here, if not null
}
}
//...
}
Hope this helps :)
Two approaches -
You can have the first method pass in an empty list of parameters to the second method:
public DataTable ExecuteStoredProcedure(string storedProcedure)
{
return ExecuteStoredProcedure(storedProcedure, new List<StoredProcedureParameters>());
}
You can pass null from the first method and add a null check in the second method, like this:
public DataTable ExecuteStoredProcedure(string storedProcedure)
{
return ExecuteStoredProcedure(storedProcedure, null);
}
...
if (storedProcedureParameters != null)
{
foreach (var parameter in storedProcedureParameters)
{
odbcCommand.Parameters.Add("#" + parameter.ParameterName, parameter.ParameterType, parameter.LengthOfParameter).Value = parameter.ParameterName;
}
}
You can add a flag to mark if you want to run the foreach or not. Of course there will be necessary to change the parameter name, and this is only one possible variant of refactor:
public DataTable ExecuteStoredProcedure(string storedProcedure, List<StoredProcedureParameters> storedProcedureParameters, bool withForEach)
{
var dataTable = new DataTable();
using (var odbcConnection = _connection)
{
using (var odbcCommand = odbcConnection.CreateCommand())
{
odbcCommand.CommandText = storedProcedure;
if(withForEach)
foreach (var parameter in storedProcedureParameters)
{
odbcCommand.Parameters.Add("#" + parameter.ParameterName, parameter.ParameterType,
parameter.LengthOfParameter).Value = parameter.ParameterName;
}
odbcCommand.CommandType = CommandType.StoredProcedure;
using (var adapter = new OdbcDataAdapter(odbcCommand))
{
adapter.Fill(dataTable);
}
}
}
return dataTable;
}
Why could you not do something like this...
public DataTable ExecuteStoredProcedure(string storedProcedure)
{
return ExecuteStoredProcedure(storedProcedure, null);
}
public DataTable ExecuteStoredProcedure(string storedProcedure, List<StoredProcedureParameters> storedProcedureParameters)
{
var dataTable = new DataTable();
using (var odbcConnection = _connection)
{
using (var odbcCommand = odbcConnection.CreateCommand())
{
odbcCommand.CommandText = storedProcedure;
if(storedProcedureParameters != null)
{
foreach (var parameter in storedProcedureParameters)
{
odbcCommand.Parameters.Add("#" + parameter.ParameterName, parameter.ParameterType,
parameter.LengthOfParameter).Value = parameter.ParameterName;
}
}
odbcCommand.CommandType = CommandType.StoredProcedure;
using (var adapter = new OdbcDataAdapter(odbcCommand))
{
adapter.Fill(dataTable);
}
}
}
return dataTable;
}
I have a result of IEnumerable from a stored procedure and i am looping through the results inorder to get the value of a column(GUID). I am unsure of how to go about on getting the Guid column from my results set in the foreach loop
this is what i have:
var results = GetGuids(instId);
foreach (var item in results)
{
}
public IEnumerable GetGuids(int id)
{
using (SqlCommand _command = new SqlCommand("StoredProc"))
{
_command.Connection = new SqlConnection(conString);
_command.Connection.Open();
_command.CommandType = CommandType.StoredProcedure;
_command.Parameters.AddWithValue("#ItemID", id);
return _command.ExecuteReader();
}
}
You can't use most of the normal linq extension methods directly on the non-generic IEnumerable... but you can call .Cast<T>() to make it an IEnumerable<T>. At that point, things get easier:
public IEnumerable<Guid> GetGuids(int id)
{
using (SqlCommand _command = new SqlCommand("StoredProc"))
{
_command.Connection = new SqlConnection(conString);
_command.Connection.Open();
_command.CommandType = CommandType.StoredProcedure;
_command.Parameters.Add("#ItemID", SqlDbType.Int).Value = id;
return _command.ExecuteReader()
.Cast<DbDataRecord>()
.Select(r => (Guid)r["GuidColumn"]);
}
}
You need to produce the results yourself from the SqlDataReader
var results = GetGuids(instId);
foreach (var item in results)
{
}
public IEnumerable<Guid> GetGuids(int id)
{
using (SqlCommand _command = new SqlCommand("StoredProc"))
{
_command.Connection = new SqlConnection(conString);
_command.Connection.Open();
_command.CommandType = CommandType.StoredProcedure;
_command.Parameters.AddWithValue("#ItemID", id);
var guids = new List<Guid>();
using (SqlDataReader reader = _command.ExecuteReader())
{
while (reader.Read()
{
guids.Add( (Guid)reader["GuidColumn"]);
}
}
}
}
I have a SQL Server 2008 database and I am working on it in the backend. I am working on asp.net/C#
SqlDataReader rdr = cmd.ExecuteReader();
while (rdr.Read())
{
//how do I read strings here????
}
I know that the reader has values. My SQL command is to select just 1 column from a table. The column contains strings ONLY. I want to read the strings (rows) in the reader one by one. How do I do this?
using(SqlDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
var myString = rdr.GetString(0); //The 0 stands for "the 0'th column", so the first column of the result.
// Do somthing with this rows string, for example to put them in to a list
listDeclaredElsewhere.Add(myString);
}
}
string col1Value = rdr["ColumnOneName"].ToString();
or
string col1Value = rdr[0].ToString();
These are objects, so you need to either cast them or .ToString().
Put the name of the column begin returned from the database where "ColumnName" is. If it is a string, you can use .ToString(). If it is another type, you need to convert it using System.Convert.
SqlDataReader rdr = cmd.ExecuteReader();
while (rdr.Read())
{
string column = rdr["ColumnName"].ToString();
int columnValue = Convert.ToInt32(rdr["ColumnName"]);
}
while(rdr.Read())
{
string col=rdr["colName"].ToString();
}
it wil work
Thought to share my helper method for those who can use it:
public static class Sql
{
public static T Read<T>(DbDataReader DataReader, string FieldName)
{
int FieldIndex;
try { FieldIndex = DataReader.GetOrdinal(FieldName); }
catch { return default(T); }
if (DataReader.IsDBNull(FieldIndex))
{
return default(T);
}
else
{
object readData = DataReader.GetValue(FieldIndex);
if (readData is T)
{
return (T)readData;
}
else
{
try
{
return (T)Convert.ChangeType(readData, typeof(T));
}
catch (InvalidCastException)
{
return default(T);
}
}
}
}
}
Usage:
cmd.CommandText = #"SELECT DISTINCT [SoftwareCode00], [MachineID]
FROM [CM_S01].[dbo].[INSTALLED_SOFTWARE_DATA]";
using (SqlDataReader data = cmd.ExecuteReader())
{
while (data.Read())
{
usedBy.Add(
Sql.Read<String>(data, "SoftwareCode00"),
Sql.Read<Int32>(data, "MachineID"));
}
}
The helper method casts to any value you like, if it can't cast or the database value is NULL, the result will be null.
For a single result:
if (reader.Read())
{
Response.Write(reader[0].ToString());
Response.Write(reader[1].ToString());
}
For multiple results:
while (reader.Read())
{
Response.Write(reader[0].ToString());
Response.Write(reader[1].ToString());
}
I know this is kind of old but if you are reading the contents of a SqlDataReader into a class, then this will be very handy. the column names of reader and class should be same
public static List<T> Fill<T>(this SqlDataReader reader) where T : new()
{
List<T> res = new List<T>();
while (reader.Read())
{
T t = new T();
for (int inc = 0; inc < reader.FieldCount; inc++)
{
Type type = t.GetType();
string name = reader.GetName(inc);
PropertyInfo prop = type.GetProperty(name);
if (prop != null)
{
if (name == prop.Name)
{
var value = reader.GetValue(inc);
if (value != DBNull.Value)
{
prop.SetValue(t, Convert.ChangeType(value, prop.PropertyType), null);
}
//prop.SetValue(t, value, null);
}
}
}
res.Add(t);
}
reader.Close();
return res;
}
I would argue against using SqlDataReader here; ADO.NET has lots of edge cases and complications, and in my experience most manually written ADO.NET code is broken in at least one way (usually subtle and contextual).
Tools exist to avoid this. For example, in the case here you want to read a column of strings. Dapper makes that completely painless:
var region = ... // some filter
var vals = connection.Query<string>(
"select Name from Table where Region=#region", // query
new { region } // parameters
).AsList();
Dapper here is dealing with all the parameterization, execution, and row processing - and a lot of other grungy details of ADO.NET. The <string> can be replaced with <SomeType> to materialize entire rows into objects.
Actually, I figured it out myself that I could do this:
while (rdr.read())
{
string str = rdr.GetValue().ToString().Trim();
}
In the simplest terms, if your query returns column_name and it holds a string:
while (rdr.Read())
{
string yourString = rdr.getString("column_name")
}
I usually read data by data reader this way. just added a small example.
string connectionString = "Data Source=DESKTOP-2EV7CF4;Initial Catalog=TestDB;User ID=sa;Password=tintin11#";
string queryString = "Select * from EMP";
using (SqlConnection connection = new SqlConnection(connectionString))
using (SqlCommand command = new SqlCommand(queryString, connection))
{
connection.Open();
using (SqlDataReader reader = command.ExecuteReader())
{
if (reader.HasRows)
{
while (reader.Read())
{
Console.WriteLine(String.Format("{0}, {1}", reader[0], reader[1]));
}
}
reader.Close();
}
}
You have to read database columnhere. You could have a look on following code snippet
string connectionString = ConfigurationManager.ConnectionStrings["NameOfYourSqlConnectionString"].ConnectionString;
using (var _connection = new SqlConnection(connectionString))
{
_connection.Open();
using (SqlCommand command = new SqlCommand("SELECT SomeColumnName FROM TableName", _connection))
{
SqlDataReader sqlDataReader = command.ExecuteReader();
if (sqlDataReader.HasRows)
{
while (sqlDataReader.Read())
{
string YourFirstDataBaseTableColumn = sqlDataReader["SomeColumn"].ToString(); // Remember Type Casting is required here it has to be according to database column data type
string YourSecondDataBaseTableColumn = sqlDataReader["SomeColumn"].ToString();
string YourThridDataBaseTableColumn = sqlDataReader["SomeColumn"].ToString();
}
}
sqlDataReader.Close();
}
_connection.Close();
I have a helper function like:
public static string GetString(object o)
{
if (o == DBNull.Value)
return "";
return o.ToString();
}
then I use it to extract the string:
tbUserName.Text = GetString(reader["UserName"]);