I can't seem to get passed this error message using this code.
System.Data.DuplicateNameException: A column named 'Url' already belongs to this DataTable.
foreach (var user in users.Users)
{
using (DataTable table = new DataTable())
{
table.Clear();
for (int i = 0; i < users.Users[0].GetType().GetProperties().Count(); i++)
{
table.Columns.Add(users.Users[0].GetType().GetProperties()[i].Name);
Console.WriteLine(table.Columns.Add(users.Users[0].GetType().GetProperties()[i].Name));
}
}
}
Any ideas?
UPDATE
var properties = users.Users[0].GetType().GetProperties();
for (int i = 0; i < properties.Count(); i++)
{
table.Columns.Add(properties[i].Name, typeof(String));
}
Because I didn't know what the type was to use the foreach. This:
var properties = users.Users[0].GetType().GetProperties();
foreach (PropertyInformation prop in properties)
{
table.Columns.Add(properties.);
Console.WriteLine(prop.Name);
}
gave me Cannot convert type 'System.Reflection.PropertyInfo' to 'System.Configuration.PropertyInformation'
Anyway I can figure out how to get the correct type in there? #barrick
The error won't lie. In the Console.WriteLine() call, you're adding the column again, which will cause the problem.
Try:
var properties = users.Users[0].GetType().GetProperties();
foreach (PropertyInfo prop in properties)
{
table.Columns.Add(prop.Name);
Console.WriteLine(prop.Name);
}
Related
I'm trying to convert a gridview datasource to a datatable.
What I have tried so far
dt = (DataTable)GridCanvas.DataSource; // Unable to cast object of type 'System.Collections.Generic.List`1 to type 'System.Data.DataTable'
Also I have tried this
Unable to cast object of type 'System.Collections.Generic.List`1[CRM.Models.Leads]' to type 'System.Windows.Forms.BindingSource'
BindingSource bindingSource = (BindingSource)GridCanvas.DataSource;
dt = (DataTable)bindingSource.DataSource;
And this
'Object reference not set to an instance of an object.'
dt = GridCanvas.DataSource as DataTable;
I'm populating my gridview in the following way
var dispatchLeads = await API.Zelkon.Leads.Dispatch.Leads(Variables.Agent.username);
GridCanvas.DataSource = dispatchLeads;
I'm trying to avoid loop solutions. Hope someone has an idea how to solve this. Thanks!
First get the List<Leads> from GridCanvas as
List<Leads> data=(List<Leads>)GridCanvas.DataSource;
Then Convert the List<Leads> to DataTable as;
DataTable dt=ToDataTable<Leads>(data);
use following methods for conversion.
public static DataTable ToDataTable<T>(List<T> items)
{
DataTable dataTable = new DataTable(typeof(T).Name);
//Get all the properties
PropertyInfo[] Props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (PropertyInfo prop in Props)
{
//Defining type of data column gives proper data table
var type = (prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>) ? Nullable.GetUnderlyingType(prop.PropertyType) : prop.PropertyType);
//Setting column names as Property names
dataTable.Columns.Add(prop.Name, type);
}
foreach (T item in items)
{
var values = new object[Props.Length];
for (int i = 0; i < Props.Length; i++)
{
//inserting property values to datatable rows
values[i] = Props[i].GetValue(item, null);
}
dataTable.Rows.Add(values);
}
//put a breakpoint here and check datatable
return dataTable;
}
I'm calling WCF Service that gives me a list of customers with specified field names in the BAL. I created a method ToDataTable as instructed on many forums (it might be wrong for this instance). I use it to convert the list into a datatable but there is a challenge that I'm facing. The error says 'Cannot implicitly convert type 'System.Data.DataTable to mHotRes.DesktopPresentation.ListFrm.ListType'.
Here is my code for binding data:
private void BindData()
{
try
{
switch (_ListType)
{
case ListType.Customers:
IHotRes res = new MHotServiceProvider().Service;
List<Customer> customer = res.CustomerSaveDataList();
_ListType = ToDataTable(customer); //the problem occurs here
break;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Here is the code for ToDataTable method:
public static DataTable ToDataTable<T>(List<T> items)
{
DataTable dataTable = new DataTable(typeof(T).Name);
//Get all the properties
PropertyInfo[] Props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (PropertyInfo prop in Props)
{
//Setting column names as Property names
dataTable.Columns.Add(prop.Name);
}
foreach (T item in items)
{
var values = new object[Props.Length];
for (int i = 0; i < Props.Length; i++)
{
//inserting property values to datatable rows
values[i] = Props[i].GetValue(item, null);
}
dataTable.Rows.Add(values);
}
//put a breakpoint here and check datatable
return dataTable;
}
If any more code samples are needed let me know.
Your reflection ToDataTable code is working correctly:
_ListType = ToDataTable(customer); //the problem occurs here
The problem is that the _ListType have different type from DataTable.
You should change the line to
DataTable tbl = ToDataTable(customer);//Your method returns DataTable
I found some solutions and suggestions on the Internet concering this problem, however, I could not yet manage to apply this to my solution. I wrote a personal MySQL wrapper which features this
public async Task<IEnumerable<DatabaseFieldSet>> QueryParamsAsync(string query, string[] parameter,
string[] value)
{
if (!IsConnected)
await ConnectAsync();
var rows = new List<DatabaseFieldSet>();
using (var cmd = CreateCommand(query))
{
foreach (var str in parameter)
{
foreach (var val in value)
{
//cmd.Parameters.Add(str, MySqlDbType.VarChar).Value = val;
cmd.Parameters.AddWithValue(str, val);
}
}
using (var reader = await cmd.ExecuteReaderAsync())
{
uint currentRowIndex = 0;
while (await reader.ReadAsync())
{
var row = new DatabaseFieldSet(currentRowIndex);
var fields = new List<DatabaseField>();
for (var i = 0; i < reader.FieldCount; ++i)
{
var column = new DatabaseReference((uint) i);
fields.Add(new DatabaseField(reader[i], column, row));
}
row.Fields = fields;
rows.Add(row);
currentRowIndex++;
}
}
}
return rows;
}
I tried to add
cmd.Parameters.Clear();
at different locations, none worked or was throwing fatal error while executing. I hope somebody can tell me where to put this single statement.
You are doing it wrong. It rather should be like below. Your double foreach causing the issue and you are eventually trying to add the same parameter again and so the error. You rather should define a counter variable and access every item in your value array.
int i = 0;
foreach (var str in parameter)
{
cmd.Parameters.AddWithValue(str, val[i]);
i++;
}
I can't work out how to get the Type of a LINQ result. My set contains both strings and bools, so I run into trouble when I try to act on the rows. I attached an incredibly rough workout using try/catch (for a laugh), but it hurts my soul and would much rather know the proper method in obtaining the Type.
private AppointmentInfoClass UpdateDataContext(DataSet phaseDataSet) {
var phaseCollection = new AppointmentInfoClass();
var Type = phaseCollection.GetType();
var properties = Type.GetProperties();
var result = from DataRow myRow in DataBindings.CompanyAppsDataSet.Tables[0].Rows
where (int)myRow["AppointmentID"] == ApptID
select myRow;
var k = 0;
foreach (DataRow row in phaseDataSet.Tables[0].Rows) {
string header;
header = row.Field<string>("Header");
foreach (var field in result) {
try {
properties[k].SetValue(phaseCollection, field.Field<string>(header));
}
catch (Exception) {
properties[k].SetValue(phaseCollection, field.Field<bool>(header).ToString());
}
}
k++;
}
return phaseCollection;
}
It will return the type you have written instead of Type
string s = field.Field<string>("ColumnName");
bool b = field.Field<bool>("ColumnName");
When using expando objects to fill my datatable, I am facing following error message when I initialize a new datarow. The exception is:
Invalid Storage Type: DBNull
public static DataTable ToCLDataTable<T>(List<T> items)
{
DataTable dataTable = new DataTable("CLWorkQueue");
//Get all the properties
DataRow dr;
var expandoDict = items[0] as IDictionary<string, object>;
foreach (var key in expandoDict.Keys)
{
if ((expandoDict[key]).GetType() == typeof(DateTime))
{
dataTable.Columns.Add(key.ToString(), typeof(DateTime));
}
else
{
dataTable.Columns.Add(key.ToString(), expandoDict[key].GetType());
}
}
for (int i = 0; i < items.Count; i++)
{
var expandoDictData = items[i] as IDictionary<string, object>;
//var values = new object[expandoDictData.Count];
int j = 0;
dr = dataTable.NewRow(); /*Though the datatable has all the required columns, but whenever i try to initialize a new row an exception occurs.*/
foreach (var key in expandoDictData.Keys)
{
//values[j] = expandoDictData[key].ToString();
dr[key] = expandoDictData[key].ToString();
j++;
}
dataTable.Rows.Add(dr);
//dataTable.Rows.Add(values);
}[enter image description here][1]
The value of the first result in your items[0] was DBNull.Vaue - which is what your SQL client populated into the structure. That's what the SQL client uses to indicate a null value. So, the actual type of the object in the first Value of the IDictionary<String,object> is DBNull...not the type it would have been if there had been a value. You might have to iterate your dictionary until you get a value before you can add that column to the datarow...or come up with a more bulletproof way of assigning the type to the column.