我必须处理(即无法控制)csv文件,其中“ N / A”是“应该”为整数的字段的可能值,并且我一直在尝试找出如何“滚动我的”自己的” TypeConversion类来处理此问题,但未能找到示例。 Josh的示例页面在该特定领域非常缺乏,而我能够找到的最接近的stackoverflow问题是2013年的this one。
然后,我找到了对NullValuesAttribute的引用,这似乎正是我所需要的,但是后来却不知道如何使用它。 VisualStudio的Intellisense也无济于事。 :)
理想情况下,我希望将“ N / A”转换为0(零)。有人可以帮忙吗?
在人们告诉我“好吧,很明显...”之前,我应该说这是我的第一个C#程序(除了教程,从字面上看),而且还有一个时间因素-否则我会很高兴地在我的探索中自己的。
[更新:在CsvHelper Parsing boolean from String尝试了最佳适应解决方案]
因此,以上述问题的解决方案为起点,我这样做了:
static void Main()
{
var rows = new List<Job>();
using (var reader = new StreamReader("mydatafile.csv")
using (var csv = new CsvReader(reader))
{
csv.Configuration.RegisterClassMap<JobMap>();
while (csv.Read())
{
var record = new Job
{
JobId = csv.GetField<int>("Job ID"),
ItemCount = csv.GetField<int>("Item Count")
};
rows.Add(record);
}
}
}
public class Job
{
public int JobId { get; set; }
public int ItemCount { get; set; }
}
public sealed class JobMap : ClassMap<Job>
{
Map(m => m.JobId);
Map(m => m.ItemCount).TypeConverterOption.NullValues("N/A");
}
我的想法是,指定NullValues将使TypeConverter将“ N / A”转换为null(因为似乎不存在与“ BooleanValues”方法等效的Int32。
不幸的是,这仍然引发了异常:
CsvHelper.TypeConversion.TypeConverterException: 'The conversion cannot be performed.
Text: 'N/A'
MemberType:
TypeConverter: 'CsvHelper.TypeConversion.Int32Converter''
因此,看起来我将不得不扩展Int32Converter。是吗?
答案 0 :(得分:1)
您可以像这样定义自定义类型转换器:
using CsvHelper;
using CsvHelper.TypeConversion;
using CsvHelper.Configuration;
public class CustomInt32Converter: Int32Converter {
public override object ConvertFromString(string text, IReaderRow row, MemberMapData memberMapData)
{
if (text == "N/A") return 0;
return base.ConvertFromString(text, row, memberMapData);
}
}
然后您可以在此行中注册转换器:
csv.Configuration.TypeConverterCache.AddConverter<int>(new CustomInt32Converter());
答案 1 :(得分:0)
虽然不是最优雅的解决方案,但至少目前对我而言有效:
从上面的代码中,删除csv.Configuration...
类。也不需要static int HandleNA (CsvReader csv, string field)
{
return (csv.GetField<string>(field) == "N/A") ? 0 : csv.GetField<int>(field);
}
行。
创建新功能
var record = new Job
{
JobId = csv.GetField<int>("Job ID"),
ItemCount = HandleNA(csv, "Item Count")
};
并在
中使用它static int Main(string[] args)
{
try
{
string destinationServer = args[0];
string destinationDatabase = args[1];
string userID = args[2];
string password = args[3];
string publishFileFullPath = args[4];
string dacpacFileFullPath = args[5];
SetupRegistryQueryExecutionTimeout();
PublishDacpacSimple(destinationServer, destinationDatabase, userID, password, publishFileFullPath, dacpacFileFullPath);
return 0; //where 0 = success
}
catch (Exception ex)
{
Console.WriteLine("Error in Main: " + ex.Message + "\n" + ex.StackTrace);
for (int i = 0; i < args.Length; i++)
{
Console.WriteLine("Value in args[" + i + "]: " + (i == 3 ? "**********" : args[i]));
}
Console.WriteLine("Failed to publish dacpac.");
//Return error state
return 1;
}
}
private static void SetupRegistryQueryExecutionTimeout()
{
//Fixes an annoying issue with slow sql servers: https://stackoverflow.com/a/26108419/2912011
RegistryKey myKey = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\VisualStudio\\12.0\\SQLDB\\Database", true);
if (myKey != null)
{
myKey.SetValue("QueryTimeoutSeconds", "0", RegistryValueKind.DWord);
myKey.Close();
}
myKey = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\VisualStudio\\14.0\\SQLDB\\Database", true);
if (myKey != null)
{
myKey.SetValue("QueryTimeoutSeconds", "0", RegistryValueKind.DWord);
myKey.Close();
}
myKey = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\VisualStudio\\15.0\\SQLDB\\Database", true);
if (myKey != null)
{
myKey.SetValue("QueryTimeoutSeconds", "0", RegistryValueKind.DWord);
myKey.Close();
}
}
private static void PublishDacpacSimple(string destinationServer,
string destinationDatabase,
string userID,
string password,
string publishFileFullPath,
string dacpacFileFullPath)
{
string connectionString = BuildConnectionString(destinationServer, destinationDatabase, userID, password);
XmlDocument xdoc = new XmlDocument();
xdoc.Load(publishFileFullPath);
DacServices ds = new DacServices(connectionString);
using (DacPackage package = DacPackage.Load(dacpacFileFullPath))
{
var options = new DacDeployOptions();
options.CommandTimeout = 600;
ds.Message += (object sender, DacMessageEventArgs eventArgs) => Console.WriteLine(eventArgs.Message.Message);
ds.Deploy(package, destinationDatabase, true, options);
}
}