I have 2 excel files that I have converted into lists. The 1st file has a complete list of all items that I need. However, the 2nd list has a small list of items that need to be changed in the 1st list.
Here's how my 1st list is constructed:
IEnumerable<ExcelRow> queryListA = from d in datapullList
select new ExcelRow
{
Company = d.GetString(0),
Location = d.GetString(1),
ItemPrice = d.GetString(4),
SQL_Ticker = d.GetString(15)
};
The 2nd list is constructed in a very similar way:
IEnumerable<ExcelRow> queryListB = from dupes in dupespullList
select new ExcelRow
{
Company = d.GetString(0),
Location = d.GetString(1),
NewCompany = d.GetString(4)
};
So, if there is a company from a particular location in 1st list that matches 2nd list, then the company gets changed to the newcompany name.
Then, my final list should have everything in 1st list but with the changes specified from 2nd list.
I've been struggling with this for a few days now. Let me know if you need more details.
[Update:] I'm pretty new to LINQ and C#. I've found this code on the web regarding Excel reader for Office 2003. How can I create the 1 list (stated above) from all the following classes?
My ExcelRow class:
class ExcelRow
{
List<object> columns;
public ExcelRow()
{
columns = new List<object>();
}
internal void AddColumn(object value)
{
columns.Add(value);
}
public object this[int index]
{
get { return columns[index]; }
}
public string GetString(int index)
{
if (columns[index] is DBNull)
{
return null;
}
return columns[index].ToString();
}
public int Count
{
get { return this.columns.Count; }
}
}
My ExcelProvider class:
class ExcelProvider : IEnumerable<ExcelRow>
{
private string sheetName;
private string filePath;
private string columnName1;
private string columnName2;
private List<ExcelRow> rows;
public ExcelProvider()
{
rows = new List<ExcelRow>();
}
public static ExcelProvider Create(string filePath, string sheetName, string columnName1, string columnName2)
{
ExcelProvider provider = new ExcelProvider();
provider.sheetName = sheetName;
provider.filePath = filePath;
provider.columnName1 = columnName1;
provider.columnName2 = columnName2;
return provider;
}
private void Load()
{
string connectionString = #"Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Extended Properties= ""Excel 8.0;HDR=YES;IMEX=1""";
connectionString = string.Format(connectionString, filePath);
rows.Clear();
using (OleDbConnection conn = new OleDbConnection(connectionString))
{
try
{
conn.Open();
using (OleDbCommand cmd = conn.CreateCommand())
{
cmd.CommandText = string.Format("SELECT * FROM [{0}$] WHERE {1} IS NOT NULL AND {2} <> \"{3}\"", sheetName, columnName1, columnName2, null);
using (OleDbDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
ExcelRow newRow = new ExcelRow();
for (int count = 0; count < reader.FieldCount; count++)
{
newRow.AddColumn(reader[count]);
}
rows.Add(newRow);
}
}
}
}
catch (Exception ex)
{ throw ex; }
finally
{
if (conn.State == System.Data.ConnectionState.Open)
conn.Close();
}
}
}
public IEnumerator<ExcelRow> GetEnumerator()
{
Load();
return rows.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
Load();
return rows.GetEnumerator();
}
}
So, using all this logic, how can I solve my problem?
//first create a dictionary of comapny whose name has been changed
var dict = queryListB.ToDictionary(x => x.Company, y => y.NewCompany);
//loop on the first list and do the changes in the first list
queryListA.ForEach( x =>
{
if(dict.Keys.Contains(x.Company))
x.Company = dict[x.Company];
});
Loop through queryListA and see if there is a matching company in queryListB. If so, then update the Company property.
Here's the code:
foreach (var companyA in queryListA)
{
var companyBMatch = queryListB.FirstOrDefault(x => x.Company == companyA.Company && x.Location == companyA.Location);
if (companyBMatch != null)
companyA.Company = companyBMatch.NewCompany;
}
I'm sure you can write simpler code to achieve the same goal but I've gone for a way that reduces the number of times you have to iterate through the first and second lists. If performance isn't an issue a simpler method that just searches the dupespullList for each element in datapullList might be appropriate.
var excelRowCreator = new ExcelRowCreator(dupespullList);
var finalRows = excelRowCreator.CreateExcelRows(datapullList);
// ...
public class ExcelRowCreator
{
/// <summary>
/// First key is company name, second is location
/// and final value is the replacement name.
/// </summary>
private readonly IDictionary<string, IDictionary<string, string>> nameReplacements;
/// <summary>
/// I don't know what type of objects your initial
/// lists contain so replace T with the correct type.
/// </summary>
public ExcelRowCreator(IEnumerable<T> replacementRows)
{
nameReplacements = CreateReplacementDictionary(replacementRows);
}
/// <summary>
/// Creates ExcelRows by replacing company name where appropriate.
/// </summary>
public IEnumerable<ExcelRow> CreateExcelRows(IEnumerable<T> inputRows)
{
// ToList is here so that if you iterate over the collection
// multiple times it doesn't create new excel rows each time
return inputRows.Select(CreateExcelRow).ToList();
}
/// <summary>
/// Creates an excel row from the input data replacing
/// the company name if required.
/// </summary>
private ExcelRow CreateExcelRow(T data)
{
var name = data.GetString(0);
var location = data.GetString(1);
IDictionary<string, string> replacementDictionary;
if (nameReplacements.TryGetValue(name, out replacementDictionary))
{
string replacementName;
if (replacementDictionary.TryGetValue(location, out replacementName))
{
name = replacementName;
}
}
return new ExcelRow
{
Company = name,
Location = location,
ItemPrice = data.GetString(4),
SQL_Ticker = data.GetString(15)
};
}
/// <summary>
/// A helper method to create the replacement dictionary.
/// </summary>
private static IDictionary<string, IDictionary<string, string>> CreateReplacementDictionary(IEnumerable<T> replacementRows)
{
var replacementDictionary = new Dictionary<string, IDictionary<string, string>>();
foreach (var dupe in replacementRows)
{
var name = dupe.GetString(0);
IDictionary<string, string> locationReplacements;
if (!replacementDictionary.TryGetValue(name, out locationReplacements))
{
locationReplacements = new Dictionary<string, string>();
replacementDictionary[name] = locationReplacements;
}
locationReplacements[dupe.GetString(1)] = dupe.GetString(4);
}
return replacementDictionary;
}
}
UPDATE : Packaged as a class and written in visual studio so there shouldn't be any grammatical errors.
Related
I have a text file having list of movie names and its parts as below:
xxx, Author1, v6
the net, author1, v7
xxx, author3, v10
DDLJ, author3, v11
the fire, author5, v6
the health, author1, v8
the health, author7, v2
the hero, author9, v11
the hero, author8, v3
I would like to get most recent version of movie name. In this case it should return "DDLJ" and "the hero".
This is what I have tried:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
namespace ProgramNamespace
{
public class Program
{
public static List<String> processData(IEnumerable<string> lines)
{
Dictionary<string, int> keyValuePairs = new Dictionary<string, int>();
foreach (var item in lines)
{
string[] readsplitted = item.Split(',');
keyValuePairs.Add(readsplitted[0], Convert.ToInt32(
Regex.Replace(readsplitted[2], "[^0-9]+", string.Empty)));
}
//List<String> retVal = new List<String>();
return retVal;
}
static void Main(string[] args)
{
try
{
List<String> retVal = processData(File.ReadAllLines(#"D:\input.txt"));
File.WriteAllLines(#"D:\output.txt", retVal);
}
catch (IOException ex)
{
Console.WriteLine(ex.Message);
}
}
}
}
Note that, if required I would like to add a helper class.
EDIT: version for duplicated keys
I rewrote the first solution I gave to take duplicated data into account. The trick is adding a progressive number before the key and separating it with an underscore: this way every key will be unique.
E.g. you will have your Dictionary filled like this:
"1_xxx", 6
"2_the net", 7
"3_xxx", 10
"4_DDLJ", 11
...
Then I remove the number (and the underscore) before providing a result.
public static List<String> processData(IEnumerable<string> lines)
{
var keyValuePairs = new Dictionary<string, int>();
int Position = 0;
foreach (var item in lines)
{
Position++;
string[] readsplitted = item.Split(',');
keyValuePairs.Add(Position.ToString() +"_" + readsplitted[0], Convert.ToInt32(Regex.Replace(readsplitted[2], "[^0-9]+", string.Empty)));
}
var MaxVersion = keyValuePairs.Values.OrderByDescending(f => f).First();
return keyValuePairs.Where(f => f.Value == MaxVersion).Select(f => string.Join("_", f.Key.Split('_').Skip(1))).ToList();
}
More in detail:
keyValuePairs.Values will return just the version numbers
.OrderByDescending(f => f).First() will sort the version numbers in descending order and pick the first, i.e. the highest
keyValuePairs.Where(f => f.Value == MaxVersion) will select the key-value pairs corresponding to the highest version above
.Select(f => f.Key) will give you the keys of your Dictionary, i.e. the titles
This way you will also keep your Dictionary; if you are doing this one time and you don't need to expand your code or reuse your models, you won't have to create other classes or make it more complicated than necessary.
For these kinds of tasks I usually prefer to create a class that represents the data we're collecting, and give it a TryParse method that will create an instance of the class based on a line of data:
public class MovieInfo
{
public string Name { get; set; }
public string Author { get; set; }
public int Version { get; set; }
public static bool TryParse(string input, out MovieInfo result)
{
result = null;
if (input == null) return false;
var parts = input.Split(',');
int version;
if (parts.Length == 3 &&
int.TryParse(parts[2].Trim().TrimStart('v'), out version))
{
result = new MovieInfo
{
Name = parts[0],
Author = parts[1],
Version = version
};
}
return result != null;
}
public override string ToString()
{
return $"{Name} (v{Version}) - {Author}";
}
}
Then it's just a matter of reading the file, creating a list of these classes, and getting all that have the highest number:
public static List<MovieInfo> processData(IEnumerable<string> lines)
{
if (lines == null) return null;
var results = new List<MovieInfo>();
foreach (var line in lines)
{
MovieInfo temp;
if (MovieInfo.TryParse(line, out temp))
{
results.Add(temp);
}
}
var maxVersion = results.Max(result => result.Version);
return results.Where(result => result.Version == maxVersion).ToList();
}
For example:
private static void Main()
{
var lines = new List<string>
{
"xxx, Author1, v6",
"the net, author1, v7",
"xxx, author3, v10",
"DDLJ, author3, v11",
"the fire, author5, v6",
"the health, author1, v8",
"the health, author7, v2",
"the hero, author9, v11",
"the hero, author8, v3",
};
var processed = processData(lines);
foreach (var movie in processed)
{
// Note: this uses the overridden ToString method. You could just do 'movie.Name'
Console.WriteLine(movie);
}
GetKeyFromUser("\nDone!! Press any key to exit...");
}
Output
This is how I would do it. This accounts for getting all the movie names that where the max version is the same.
public static List<String> processData(string fileName)
{
var lines = File.ReadAllLines(fileName);
var values = lines.Select(x =>
{
var readsplitted = x.Split(',');
return new { Name = readsplitted[0], Verison = int.Parse(readsplitted[2].Replace("v", string.Empty))};
});
var maxValue= values.Max(x => x.Verison);
return values.Where(v => v.Verison == maxValue)
.Select(v => v.Name)
.ToList();
}
static void Main(string[] args)
{
try
{
List<String> retVal = processData(#"D:\output.txt");
}
catch (IOException ex)
{
Console.WriteLine(ex.Message);
}
}
create a Movie class in order to initialize objects for each row that represents a movie.
split the whole string passed to processData() first by new line that by ','.
extract the number of the version of each movie (sperate it from "v") see: extractNumberFromString() method.
find the max version number and get (using linq query) all the movies that share the maximum version number.
public static List<Movie> processData(string s)
{
// list to store all movies
List<Movie> allmovies = new List<Movie>();
// first split by new line
var splitbynewline = s.Split('\n');
// split by ',' and initilize object
foreach (var line in splitbynewline)
{
var moviestring = line.Split(',');
// create new movie object
Movie obj = new Movie { Name = moviestring[0], Author = moviestring[1], Version = moviestring[2] };
obj.VersionNumber = extractNumberFromString(moviestring[2]);
allmovies.Add(obj);
}
// get the max version number
double maxver = allmovies.Max(x => x.VersionNumber);
// set and returen list that containes all movies with max version
List<Movie> result = allmovies.Where(x => x.VersionNumber == maxver).ToList();
return result;
}
/// <summary>
///
/// convert number that exist in a string to an int32 for example sdfdf43gn will return as 43
/// </summary>
/// <param name="value">string that contains inside him as digits</param>
/// <returns>int32</returns>
public static double extractNumberFromString(string value)
{
string returnVal = string.Empty;
System.Text.RegularExpressions.MatchCollection collection = System.Text.RegularExpressions.Regex.Matches(value, "\\d+");
foreach (System.Text.RegularExpressions.Match m in collection)
{
returnVal += m.ToString();
}
return Convert.ToDouble(returnVal);
}
public class Movie
{
public string Name;
public String Author;
public string Version;
public double VersionNumber;
}
i am trying to convert data table to list in web service to get it in java script . i tried the below code
rows = (from p in dt.AsEnumerable()
select new TableProperty() { }).ToList<TableProperty>();
for (int i = 0; i < rows.Count; i++)
{
// Get List of table Properties..
List<TableProperty> tProperties = new List<TableProperty>();
for (int j = 0; j < dt.Columns.Count; j++)
{
try
{
TableProperty propertyValue = new TableProperty()
{
name = dt.Columns[j].ToString(),
serial = dt.Columns[j].ToString(),
address = dt.Columns[j].ToString(),
mobile = dt.Columns[j].ToString(),
password = dt.Columns[j].ToString()
};
tProperties.Add(propertyValue);
}
catch (Exception ex)
{
ex.ToString();
}
}
}
return rows;
where is dt is my data table ,TableProperty is the class which i set and get my properties
when i get it in java script , my value returns null
function draw_Result(ddata) {
alert(ddata.length);
for (var i = 0; i < ddata.length; i++) {
alert("for");
try
{
var post = ddata[i].name.toString();
alert(post);
}
catch (e)
{
alert(e.message);
}
}
}
any help
rows = (from p in dt.AsEnumerable()
select new TableProperty() { }).ToList<TableProperty>();
Have you tried debugging the program to see what rows is after you assign it like that?
Also, you seem to first be assigning the rows, then looping over that collection only to create a completely new collection tProperties (which would probably contain what you'd expect) and at the end you return rows again. What is the purpose of tProperties?
It looks as if rows was a list of TableProperty objects which are empty - since for each row (from p in dt.AsEnumerable()) you select an empty object (select new TableProperty() { }) and at the end convert the enumerable to a list of still empty objects.
You'd need to do your mapping either at the point when you create the TableProperty - but that would imply that you know how many columns there are:
rows = (from p in dt.AsEnumerable()
select new TableProperty() {
name = p[0].ToString(),
serial = p[1].ToString(),
address = p[2].ToString(),
mobile = p[3].ToString(),
password = p[4].ToString()
}).ToList<TableProperty>();
If you don't know how many columns to expect, you can always go with just the plain Enumerable - i.e. do the for loops using
var rows = dt.AsEnumerable()
Just a tip: You could always make an extension to the DataTable object. When you so-call extend the DataTable object, you make it possible to do this:
List<TableProperties> ListOfTableProperties = YourDataTable.DataTableToList<TableProperties>();
Here is how to do it:
Say you have this data model (a class):
public class TableProperties
{
public int Indexer { get; set; }
public string DisplayName { get; set; }
public string TypeName { get; set; }
}
.. and you have this data table to work with:
DataTable tbl = new DataTable("test");
tbl.Columns.Add("Indexer");
tbl.Columns.Add("DisplayName");
tbl.Columns.Add("TypeName");
tbl.Rows.Add(2, "teststring1", "teststring2");
.. and when you do this:
List<TableProperties> urk = tbl.DataTableToList<TableProperties>();
... you get a list of type TableProperties.
The extension you need for this can be put in a static class of its own somewhere in your project. Here is the code for making such a class:
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Web;
public static class ExtensionMethods
{
/// <summary>
/// Converts a DataTable to a strongly typed list
/// </summary>
/// <typeparam name="T">Generic object</typeparam>
/// <param name="table">DataTable</param>
/// <returns>List with generic objects</returns>
public static List<T> DataTableToList<T>(this DataTable table) where T : class, new()
{
try
{
List<T> list = new List<T>();
foreach (var row in table.AsEnumerable())
{
T obj = new T();
foreach (var prop in obj.GetType().GetProperties())
{
try
{
PropertyInfo propertyInfo = obj.GetType().GetProperty(prop.Name);
propertyInfo.SetValue(obj, Convert.ChangeType(row[prop.Name], propertyInfo.PropertyType), null);
}
catch
{
continue;
}
}
list.Add(obj);
}
return list;
}
catch
{
return null;
}
}
}
Note that for example integers are not enclosed in quotes in the final result; there is a type check there, in the extension method. Remember that the names of the properties must correspond to the field names of the DataTable object.
If you do not know the field names and/or do not have a data model at hand, you can use Linq.
Sorry if the title does not reflect what I actually want.
I'm creating a generic class for selecting, updating, inserting and deleting dates from and to a database.
Basically, I want a function that gives me back an ObservableCollection<"can be anything"> ==> Where anything is a class and not strings. I would like to know if it is possible to do this, if yes, please,help me how I can achieve this.
this is my starting point:
//class a
public static ObservableCollection<ContactPerson> contactPersons = new ObservableCollection<ContactPerson>();
public static ObservableCollection<ContactPerson> getContactPerson()
{
contactPersons = (ObservableCollection<ContactPerson>)DBConnection.GetDataOutDatabase(typeof(ContactPerson), "Contactpersoon");
return contactPersons;
}
//class b
public static Object GetDataOutDatabase(Type myType,String table)
{
ObservableCollection<Object> objecten = new ObservableCollection<Object>();
string sql = "SELECT * FROM " + table;
DbDataReader reader = Database.GetData(sql);
while (reader.Read())
{
objecten.Add(Create(myType, reader));
}
return objecten;
}
private static Object Create(Type myType, IDataRecord record)
{
PropertyInfo[] myPropertyInfo = myType.GetProperties(BindingFlags.Public | BindingFlags.Instance);
for (int i = 0; i < myPropertyInfo.Length; i++)
{
PropertyInfo myPropInfo = (PropertyInfo)myPropertyInfo[i];
String name = myPropInfo.Name;
Type type = myPropInfo.PropertyType;
}
return null;
}
And this is what I ultimately want to get. Is this possible?
//ContactPerson cp = new ContactPerson();
//cp.ID = (record["ID"].ToString());
//cp.Name = record["Name"].ToString();
//cp.Company = record["Company"].ToString();
//cp.JobTitle = new ContactPersonTitle()
//{
// Name = record["JobTitle"].ToString(),
//};
//cp.JobRole = new ContactPersonType()
//{
// Name = record["JobRole"].ToString(),
//};
//cp.City = record["City"].ToString();
//cp.Email = record["Email"].ToString();
//cp.Phone = record["Phone"].ToString();
//cp.Cellphone = record["Cellphone"].ToString();
Many thanks!
You can actually do this with reflection in generic methods.
public class DBConnection
{
public static ObservableCollection<T> GetDataOutDatabase<T>(string table)
{
var objecten = new ObservableCollection<T>();
string sql = "SELECT * FROM " + table;
DbDataReader reader = Database.GetData(sql);
while (reader.Read())
{
objecten.Add(Create<T>(reader));
}
return objecten;
}
public static T Create<T>(IDataRecord record)
{
var properties = typeof(T).GetProperties();
var returnVal = Activator.CreateInstance(typeof(T));
properties.ToList().ForEach(item =>
{
try
{
if (item.PropertyType.IsPrimitive)
{
item.SetValue(returnVal, Convert.ChangeType(record[item.Name].ToString(), item.PropertyType),null);
}
else
{
object[] parameters = {record};
var value =
typeof(DBConnection).GetMethod("Create").MakeGenericMethod(item.PropertyType).Invoke(null, parameters);
item.SetValue(returnVal,value,null);
}
}
catch
{
Write("Property Not Found");
}
});
return (T)returnVal;
}
}
The example above does assume that all properties names match the column names you are retrieving from your database communication. For instance in the ContactPersonTitle above rather than Name you would need to have JobTitle as the property name.
Not as you are currently doing it. You should look into the entity framework which allows translation of database tables datacollections.
have a look at:
http://www.codeproject.com/Articles/363040/An-Introduction-to-Entity-Framework-for-Absolute-B
I have a simple question. During i create a dictionary in c#, half of the dictionary contains question marks. Here is my situration:
SourceCode:
/// <summary>
/// Get Member
/// </summary>
/// <param name="Binder"></param>
/// <param name="Result"></param>
/// <returns></returns>
public override bool TryGetMember(GetMemberBinder Binder, out object Result)
{
if (Binder.Name == "AsDictionary")
{
IDictionary<string, string> cValues = new Dictionary<string, string>();
foreach (var cValue in myValues)
{
string cVal = "";
if (cValue.Value == null)
{
cVal = "";
}
else
{
cVal = cValue.Value.ToString();
}
cValues.Add(cValue.Key, cVal);
}
Result = cValues;
return true;
}
int cCount = myValues.Where(Item => Item.Key.ToLower() == Binder.Name.ToLower()).ToList().Count;
if (cCount == 0)
{
Result = null;
return false;
}
else
{
Result = myValues.Where(Item => Item.Key.ToLower() == Binder.Name.ToLower()).First().Value;
}
return true;
}
myValues is also a ObservableCollection:
private ObservableCollection<DynamicSqlValue> myValues;
DynamicSqlValue is a very simple class:
public class DynamicSqlValue
{
public string Key
{
get;
set;
}
public object Value
{
get;
set;
}
}
Thank you for your help!
Must be some kind of visual studio issue or maybe you're running out of memory. Have you tried logging the values?
I would go a step farther than Patryk and ask why you aren't doing myValues.ToDictionary. Also, the .Where, .ToList, and .Count should be as simple as:
myValues.Any(kvp => kvp.Key.Equals(Binder.Name, StringComparison.InvariantCultureIgnoreCase))
That function should really only be like 4 or 5 lines of code.
It's not answer for Your question (sorry for that) but i have some refactor tip of Your code:
Make Your foreach like that:
foreach (var cValue in myValues)
{
cValues.Add(cValue.Key, cValue.Value != null ? cValue.Value.ToString() : string.Empty);
}
And create local variable from linq query:
var binderMyValues = myValues.Where(Item => Item.Key.ToLower() == Binder.Name.ToLower());
to use it like e.g.
int cCount = binderMyValues.ToList().Count;
or...
Result = binderMyValues.First().Value;
I need to write a script which merges a list with a dictionary to create a third dictionary. I'm pretty new to programming and am struggling with the basics here.
So far I've created the following class which generates a list of dates. I have another class which generates a dictionary and I want to basically create a third dictionary which contains the dates and data which do not exist already in the first list.
Any ideas how I should do this? Thanks.
class StartList: IDisposable
{
private readonly string[] names = new[] { "name1", "name2", "name3"};
private SqlConnection conn;
private Dictionary<string, List<DateTime>> startData = new Dictionary<string, List<DateTime>>();
public StartList()
{
this.conn = new SqlConnection(ConfigurationManager.ConnectionStrings["NameCon"].ConnectionString);
this.conn.Open();
}
private void Dispose()
{
if (this.conn != null)
{
if (this.conn.State != ConnectionState.Closed)
{
try
{
this.conn.Close();
}
catch
{
}
}
this.conn.Dispose();
this.conn = null;
}
}
public void ImportStartData()
{
foreach (string name in this.names)
{
this.startData.Add(name, this.ImportStartData(name));
}
}
public List<DateTime> ImportStartData(string name)
{
List<DateTime> result = new List<DateTime>();
string sqlCommand = string.Format("SELECT * FROM {0}_Index ", name);
using (SqlCommand cmd = new SqlCommand(sqlCommand, this.conn))
{
cmd.CommandType = CommandType.Text;
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
result.Add(reader.GetDateTime(0));
}
}
}
return result;
}
}
First you need to modify the below code block
From:
public void ImportStartData()
{
foreach (string name in this.names)
{
this.names.Add(name, this.ImportStartData(name));
}
}
To:
public void ImportStartData()
{
foreach (string name in this.names)
{
if(!startData.ContainsKey(name)) //If this check is not done, then Dictionary will throw, duplicate key exception.
{
this.startData.Add(name, this.ImportStartData(name));
}
}
}
Anyway, the better approach would be, if possible first read the name as well as Date from database, possibly into a DataTable and then using LINQ/foreach loop, group the results by name.