我必须编写一个可怕的界面,将数据从我们旧应用程序中的数百个数据文件导入新数据库,这些数据文件具有硬编码的所有内容(显示的数据类似于Excel电子表格,它允许我们将数据导出到逗号分隔值。)
我可以用标题名称全部阅读。
由此,我可以为要在Sql CE数据库中使用的列生成一个名称。
目前,数据包括float
,int
,DateTime
,bit
,char
和string
。
我已经想出了一个方式来做这个(在我们所有的数据上都未经测试),但是非常感谢那些知道如何更好地编码的人的任何帮助。
除非有人不理解我的要求,否则下面的代码无需通读。
public enum MyParameterType { NA, Float, Bool, Char, Date, Int, String }
class MyParameter {
public MyParameter(string name, string value) {
if (String.IsNullOrEmpty(name) || String.IsNullOrEmpty(value)) {
throw new NotSupportedException("NULL values are not allowed.");
}
Name = name.Trim();
Value = value.Trim();
Type = MyParameterType.NA;
if (-1 < Value.IndexOf('.')) { // try float
float f;
if (float.TryParse(Value, out f)) {
string s = f.ToString();
if (s == Value) {
Parameter = new SqlCeParameter(AtName, SqlDbType.Float) { Value = f };
Type = MyParameterType.Float;
}
}
}
if (Type == MyParameterType.NA) {
bool b;
if (bool.TryParse(Value, out b)) {
Parameter = new SqlCeParameter(AtName, SqlDbType.Bit) { Value = b };
Type = MyParameterType.Bool;
}
}
if (Type == MyParameterType.NA) {
if (Value.Length == 1) {
char c = Value[0];
Parameter = new SqlCeParameter(AtName, SqlDbType.Char) { Value = c };
Type = MyParameterType.Char;
}
}
if (Type == MyParameterType.NA) {
DateTime date;
if (DateTime.TryParse(Value, out date)) {
Parameter = new SqlCeParameter(AtName, SqlDbType.DateTime) { Value = date };
Type = MyParameterType.Date;
}
}
if (Type == MyParameterType.NA) {
if (50 < Value.Length) {
Value = Value.Substring(0, 49);
}
Parameter = new SqlCeParameter(AtName, SqlDbType.NVarChar, 50) { Value = this.Value };
Type = MyParameterType.String;
}
}
public string AtName { get { return "@" + Name; } }
public string Name { get; set; }
public MyParameterType Type { get; set; }
public SqlCeParameter Parameter { get; set; }
public string Value { get; set; }
}
我最担心的是我不想错误地解释其中一个输入(比如布尔值为char)。
我也在寻找一种方法来比较MyParameter
的新实例(即如果它少于一种类型,请尝试其他类型)。
看到一些很酷的新表达式来产生这个奖励积分!
答案 0 :(得分:2)
我认为问题不在于该代码,它似乎是一种知道的方式,因为你总是接收params作为字符串,我认为你可以更好地尝试它,但在数据提取步骤中,
也许使用标题列,您可以“解析它们”到类型..
并尝试
Convert.ChangeType(yourValue, typeof(string, double,etc))
答案 1 :(得分:2)
给出一些抽象的CsvReader
:
using (var reader = new CsvReader(file))
{
TableGuess table = new TableGuess { Name = file };
// given: IEnumerable<string> CsvReader.Header { get; }
table.AddColumns(reader.Header);
string[] parts;
while (null != (parts = reader.ReadLine()))
{
table.AddRow(parts);
}
}
您的ColumnGuess
:
class ColumnGuess
{
public string Name { get; set; }
public Type Type { get; set; }
public int Samples { get; private set; }
public void ImproveType(string value)
{
if (this.Samples > 10) return;
this.Samples++;
float f; bool b; DateTime d; int i;
if (Single.TryParse(value, out f))
{
this.Type = typeof(float);
}
else if (Boolean.TryParse(value, out b))
{
this.Type = typeof(bool);
}
else if (DateTime.TryParse(value, out d))
{
this.Type = typeof(DateTime);
}
else if (value.Length == 1 && this.Type == null && !Char.IsDigit(value[0]))
{
this.Type = typeof(char);
}
else if (this.Type != typeof(float) && Int32.TryParse(value, out i))
{
this.Type = typeof(int);
}
}
}
TableGuess
将包含猜测的列和行:
class TableGuess
{
private List<string[]> rows = new List<string[]>();
private List<ColumnGuess> columns;
public string Name { get; set; }
public void AddColumns(IEnumerable<string> columns)
{
this.columns = columns.Select(cc => new ColumnGuess { Name = cc })
.ToList();
}
public void AddRow(string[] parts)
{
for (int ii = 0; ii < parts.Length; ++ii)
{
if (String.IsNullOrEmpty(parts[ii])) continue;
columns[ii].ImproveType(parts[ii]);
}
this.rows.Add(parts);
}
}
您可以添加TableGuess
AsDataTable()
方法:
public DataTable AsDataTable()
{
var dataTable = new dataTable(this.Name);
foreach (var column in this.columns)
{
dataTable.Columns.Add(new DataColumn(
column.Name,
column.Type ?? typeof(string)));
}
foreach (var row in this.rows)
{
object[] values = new object[dataTable.Columns.Count];
for (int cc = 0; cc < row.Length; ++cc)
{
values[cc] = Convert.ChangeType(row[cc],
dataTable.Columns[cc].DataType);
}
dataTable.LoadRow(values, false);
}
return dataTable;
}
您可以使用SqlCeDataAdapter
移动DataTable
中的数据(将表本身添加到数据库之后)。
答案 2 :(得分:1)
这个伪代码怎么样 - 我认为这对你来说应该足够快。这是非常伪的 - 所以“字符串”,“字符”等只是枚举值的占位符或者你想要的任何其他东西。
For first data row in data file
For each column in row
TypeOfCol(column) = <best first guess>
Next
Next
For each data row in data file
For each column in row
If TypeOfCol(column) = "string"
Continue For
If TypeOfCol(column) = "char"
If columnValue has more than one character
TypeOfCol(column) = "string"
Continue For
If TypeOfCol(column) = "bit"
If columnValue isn't 1 or 0
TypeOfCol(column) = "int" // Might not be an int - next If will pick up on that...
If TypeOfCol(column) = "int"
If columnValue isn't integer
TypeOfCol(column) = "float"
If TypeOfCol(column) = "float"
If columnValue isn't a float
TypeOfCol(column) = If(columnValue has more than one character then "string" else "char")
If TypeOfCol(column) = "datetime"
If columnValue isn't a date/time
TypeOfCol(column) = "string"
Next
Next