How to insert items into a SQL Server database using reflection? - c#

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) {
}
}
}
}`

Related

How To Convert List Into DataTable For SQlBulkCopy

I have an object class which I cobvert into a List. I would like to convert the class into a list, so I can do a SQLBulkCopy, as my current method takes long to write data intop SQL database table.
class ExtractedInfo
{
public string Date { get; set; }
public string Client { get; set; }
public string Path { get; set; }
}
List<ExtractedInfo> extractedList = new List<ExtractedInfo>();
try
{
Console.WriteLine("Writing to DB");
using (SqlConnection conn = new SqlConnection(connectionStringPMT))
{
conn.Open();
SqlCommand cmd =
new SqlCommand(
"IF NOT EXISTS (SELECT 1 FROM [FileTrckT] WHERE Path = #Path) " +
"INSERT INTO [FileTrckT] (Date, Client, Path, DateAddedToDb, FileName) " + // dont forget to add "DateAddedToDb" on live code
"VALUES (#Date, #Client, #Path, #DateAddedToDb, #FileName)");// dont forget to add " #DateAddedToDb" on live code
cmd.CommandType = CommandType.Text;
cmd.Connection = conn;
cmd.Parameters.Add("#Date", DbType.DateTime);
cmd.Parameters.Add("#Client", DbType.String);
cmd.Parameters.Add("#Path", DbType.String);
cmd.Parameters.Add(#"DateAddedToDb",DbType.DateTime); //uncomment on live code
cmd.Parameters.Add("#FileName", DbType.String);
foreach (var extractedRecord in extractedList)
{
cmd.Parameters[0].Value = extractedRecord.Date;
cmd.Parameters[1].Value = extractedRecord.Client;
cmd.Parameters[2].Value = extractedRecord.Path;
cmd.Parameters[3].Value = DateTime.Now; //uncomment on live code
cmd.Parameters[4].Value = extractedRecord.Path.Substring(extractedRecord.Path.LastIndexOf("/")+1);
cmd.ExecuteNonQuery();
}
conn.Close();
}
} catch(Exception ex)
{
Console.WriteLine(ex.Message.ToString());
Console.WriteLine("Error occured whilst inserting data into sql table FiletrckT");
log.Info("Error occured whilst inserting data into sql table FiletrckT");
log.Error(DateTime.Now + ": " + ex.Message.ToString());
}
}
catch(Exception ex)
{
log.Error(DateTime.Now.ToString() + " " + ex.Message.ToString());
Console.WriteLine(ex.Message);
}
}
A better option is to use FastMember's ObjectReader to create an IDataReader on top of the collection or IEnumerable. This way you avoid doubling memory usage by copying everything into a DataTable.
From the repo's samples:
using(var bcp = new SqlBulkCopy(connection))
using(var reader = ObjectReader.Create(myList, "Id", "Name", "Description"))
{
bcp.DestinationTableName = "SomeTable";
bcp.WriteToServer(reader);
}
You don't need to pass a field list if you want to export all fields.
The library is available through NuGet
If you want to create a DataTable for other reasons, you can use MoreLINQ's ToDataTable. It works the same as ToList or ToArray but generates a DataTable. The full MoreLINQ library is available through NuGet. Individual extensions are available as code packages, eg ToDataTable's source is available here
UPDATE
The ExtractedInfo class doesn't seem to match the fields of the FileTrckT table. This can be fixed by adding a Select call that converts the ExtractedInfo objects to the form expected by the table, eg:
var itemsToAdd= from it in extractedList
select new { Date= DateTime.Parse(it.Date), //Or ParseExact
it.Client,
it.Path,
DateAddedToDb = DateTime.Now,
FileName = it.Path.Substring(it.Path.LastIndexOf("/")+1)
};
var fields=new []{"Date", "Client", "Path","DateAddedToDb","FileName"};
using(var bcp = new SqlBulkCopy(connection))
using(var reader = ObjectReader.Create(itemsToAdd, fields))
{
bcp.DestinationTableName = "FileTrckT";
bcp.WriteToServer(reader);
}
You can write your own generic conversion method, like this for example:
private DataTable ConvertToDatatable<T>(IList<T> data)
{
var props = TypeDescriptor.GetProperties(typeof(T));
DataTable table = new DataTable();
foreach (PropertyDescriptor prop in props)
table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
foreach (T item in data)
{
DataRow row = table.NewRow();
foreach (PropertyDescriptor prop in props)
row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
table.Rows.Add(row);
}
return table;
}
or an extension method:
static class MyExtenstions
{
public static DataTable ToDataTable<T>(this IList<T> data)
{
var props = TypeDescriptor.GetProperties(typeof(T));
DataTable table = new DataTable();
foreach (PropertyDescriptor prop in props)
table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
foreach (T item in data)
{
DataRow row = table.NewRow();
foreach (PropertyDescriptor prop in props)
row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
table.Rows.Add(row);
}
return table;
}
}

c# genereic sql context patameter

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");
});

file already in use exception after using dispose and SuppressFinalize on MS access File

I am working on software that make changes in database through GUI. I want to compact database after user clicks save. After save user can continue to use software or close, so I am not using "using". I have created databaseAccess object which holds OleDbConnection connection object with few others. This is my database access class.
using System;
using System.Collections.Generic;
using System.Data.OleDb;
using System.Data;
using System.Diagnostics;
using System.Windows.Forms;
namespace TreeTool
{
public class DataBaseAccess
{
#region Properties
private string m_directory;
public List<string> selectedTableNames;
private Dictionary<String, DataTable> selectedTables;
private OleDbConnection mdbConnection;
DataTable dataTable;
//Constructor
public DataBaseAccess()
{
selectedTableNames = new List<string>();
selectedTables = new Dictionary<string, DataTable>();
}
public string directory
{
get
{
return m_directory;
}
set
{
m_directory = value;
}
}
#endregion
public List<string> GetAllTableNames()
{
if (dataTable != null)
{
List<string> tableList = new List<string>();
for (int i = 0; i < dataTable.Rows.Count; i++)
{
string TableName = dataTable.Rows[i][2].ToString();
tableList.Add(TableName);
}
return tableList;
}
return null;
}
/// <summary>
/// Returns Table Columns
/// </summary>
/// <returns></returns>
public DataTable GetTable(string TableName)
{
DataTable mdbTable;
if (selectedTables.TryGetValue(TableName, out mdbTable))
{
return mdbTable;
}
else
{
mdbTable = new DataTable();
//mdbConnection.Open();
string mdbCommandString = "SELECT * FROM [" + TableName + "]";
OleDbDataAdapter QueryCommand = new OleDbDataAdapter(mdbCommandString, mdbConnection);
QueryCommand.Fill(mdbTable);
//mdbConnection.Close();
selectedTables.Add(TableName, mdbTable);
return mdbTable;
}
}
public void SetTable(String TableName, DataTable dataTable)
{
//mdbConnection.Open();
OleDbCommand ac = new OleDbCommand("delete from [" + TableName + "]", mdbConnection);
ac.ExecuteNonQuery();
foreach (DataRow row in dataTable.Rows)
{
String query = "INSERT INTO [" + TableName + "] (TaskID, HTMLTopic, nRelative, [Group], nKey,"
+ " [nText], nImage, nSelImage, nFontName, nFontInfo, Keywords) VALUES (#TaskID,"
+ " #HTMLTopic, #nRelative, #Group, #nKey, #nText, #nImage, #nSelImage, #nFontName, "
+ " #nFontInfo, #Keywords)";
OleDbCommand command = new OleDbCommand(query, mdbConnection);
command.Parameters.AddWithValue("#TaskID", row["TaskID"]);
command.Parameters.AddWithValue("#HTMLTopic", row["HTMLTopic"]);
command.Parameters.AddWithValue("#nRelative", row["nRelative"]);
command.Parameters.AddWithValue("#Group", row["Group"]);
command.Parameters.AddWithValue("#nKey", row["nKey"]);
command.Parameters.AddWithValue("#nText", row["nText"]);
command.Parameters.AddWithValue("#nImage", row["nImage"]);
command.Parameters.AddWithValue("#nSelImage", row["nSelImage"]);
command.Parameters.AddWithValue("#nFontName", row["nFontName"]);
command.Parameters.AddWithValue("#nFontInfo", row["nFontInfo"]);
command.Parameters.AddWithValue("#Keywords", row["Keywords"]);
command.ExecuteNonQuery();
}
//mdbConnection.Close();
}
internal bool validTable(string TableName)
{
DataTable mdbTable = new DataTable();
//mdbConnection.Open();
string mdbCommandString = "SELECT * FROM [" + TableName + "]";
OleDbDataAdapter QueryCommand = new OleDbDataAdapter(mdbCommandString, mdbConnection);
QueryCommand.Fill(mdbTable);
//mdbConnection.Close();
// check if table contains all columns necessary
String[] columnNames = new string[] { "TaskID" , "HTMLTopic", "nRelative", "Group", "nKey",
"nText", "nImage", "nSelImage", "nFontName", "nFontInfo", "Keywords"};
Boolean missingColumn = false;
DataColumnCollection columns = mdbTable.Columns;
foreach (String columnName in columnNames)
{
if (columns.Contains(columnName) == false)
{
// print the message
MessageBox.Show("Database: " + directory + " Table: " + TableName + " is missing column \"" + columnName
+ "\". Add it to make changes.",
"Missing column",
MessageBoxButtons.OK,
MessageBoxIcon.Exclamation,
MessageBoxDefaultButton.Button1);
missingColumn = true;
}
}
if (missingColumn == true)
{
return false;
}
return true;
}
public void insertTable(String tableName)
{
selectedTableNames.Add(tableName);
}
public List<String> getSelectedTables()
{
return selectedTableNames;
}
public Boolean isConnected()
{
if (mdbConnection == null)
{
return false;
}
return true;
}
public void connect()
{
if (mdbConnection == null)
{
String m_mdbDirectory = #"Provider=Microsoft.JET.OLEDB.4.0;Data Source=" + m_directory;
mdbConnection = new OleDbConnection(m_mdbDirectory);
mdbConnection.Open();
string[] restrictions = new string[4];
restrictions[3] = "Table";
dataTable = mdbConnection.GetSchema("TABLES", restrictions);
//mdbConnection.Close();
}
}
public void disconnect()
{
mdbConnection.Close();
mdbConnection.Dispose();
GC.SuppressFinalize(mdbConnection);
mdbConnection = null;
}
public void clearSelectedTables()
{
selectedTableNames.Clear();
}
}
}
Save and compact functions are like this
private void save()
{
foreach(DataBaseAccess database in databases)
{
// save changes code
database.disconnect();
CompactAndRepairAccessDB(database.directory);
database.connect();
}
}
private void CompactAndRepairAccessDB(string accessFile)
{
string tempFile = #"temp.mdb";
FileInfo temp = new FileInfo(tempFile);
// Required COM reference for project:
// Microsoft Office 14.0 Access Database Engine Object Library
var dbe = new Microsoft.Office.Interop.Access.Dao.DBEngine();
try
{
dbe.CompactDatabase(accessFile, tempFile);
temp.CopyTo(accessFile, true);
temp.Delete();
}
catch (Exception e)
{
Console.WriteLine("Error: " + e.Message);
}
}
The exception happens on line "dbe.CompactDatabase(accessFile, tempFile);".
In the code in all the methods where you use OleDbDataAdapter and OleDbCommand make sure to use the using-Pattern on these objects. They can keep the mdb file open even though the actual connection is already disposed.
Methods that require modification seem to be GetTable, SetTable and ValidTable.

c# wpf datagrid add row

I need to insert values in a table that have different columns from time to time. The columns and row data are updated from MySql. Each row values are in single MySql cells with the following format:
ColumnName{Delimiter}Value{BigDelimiter}Column2Name{Delimiter}Value2...
So I split the cell strings to get the column header and value, as the user can rearrange columns, modify, delete or insert new ones. I searched for a solution, though I get nothing but empty rows:
private void GetDataTableValues()
{
if (dtData.Value != null)
{
try
{
LoadFields();
dgwDataMain.Items.Clear();
dgwDataMain.Columns.Clear();
foreach (Fields field in fields)
{
DataGridTextColumn column = new DataGridTextColumn();
column.Header = field.name;
column.Binding = new Binding(field.name);
dgwDataMain.Columns.Add(column);
}
if (connection.State == System.Data.ConnectionState.Broken || connection.State == System.Data.ConnectionState.Closed)
connection.Open();
command.Parameters.Clear();
DateTime dt = dtData.Value ?? DateTime.Now;
command.Parameters.Add("#date", MySqlDbType.Date, 50).Value = dt.ToString("yyyy-MM-dd");
command.CommandText = "SELECT value,team FROM sessions WHERE date=#date";
List<string> teams = new List<string>();
foreach (Control ctrl in panDataFilter.Children)
if ((ctrl as CheckBox).IsChecked == true)
teams.Add(Convert.ToString((ctrl as CheckBox).Content));
using (MySqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
bool v = false;
if (teams.Contains(reader[1].ToString()) || teams.Count == 0)
v = true;
if (v)
{
DatabaseObject obj = new DatabaseObject();
List<string> str2 = new List<string>(reader[0].ToString().Split(new string[] { "</s&p>" }, StringSplitOptions.None).ToList());
obj.Items = new List<string>(str2.Count);
foreach (string str in str2)
{
List<string> item = new List<string>(str.Split(new string[] { "<&p>" }, StringSplitOptions.None).ToList());
int index = dgwDataMain.Columns.Single(c => c.Header.ToString() == item[0].ToString()).DisplayIndex;
obj.Items.Insert(index, item[1].ToString());
}
dgwDataMain.Items.Add(obj);
}
}
}
}
catch (MySqlException ex)
{
MessageBox.Show(ex.ErrorCode.ToString() + ": " + ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Exclamation);
}
}
}
public class DatabaseObject
{
public List<string> Items = new List<string>();
}
to delete extra row from datagrid is, just make property...
Canuseraddrows="false";
Please use Observablecollection to bind the data grid. By using observablecollection easily you can add or delete item and not required to reset the data source of data grid.
Sample Code:
observableCollection myClass = new
observableCollection();
myClass.add(Class)

how to retrieve values by LINQ in asp.net?

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)

Categories