I'm importing a row with CSVHelper into the following class:
public class RequestMonitoring
{
public string PNdsPn { get; set; }
[Required]
public virtual Stamp PUsrCrStatus { get; set; }
// many other properties
}
with Stamp looking like this:
public class Stamp
{
public int Weight { get; set; }
[Required]
public string MachineName { get; set; }
// many other properties
}
And a CSV looking like this:
$P_NDS_PN;#P_USR_CR_Staus; ...
CTD_037453;SYS complete; ...
Where "SYS complete" is the "MachineName" of the stamp.
But the typeconversion doesn't work like i expected. If i'm using a CustomTypeConverter it doesn't fire it's ConvertFromString method except i change the "PUsrCrStatus" property to type string which makes no sense in my opinion.
So i tried inline conversion with ConvertUsing like this:
classMap.Map(requestMonitoring => requestMonitoring.PUsrCrStatus)
.ConvertUsing(row = > _context.Stamps.SingleOrDefault(stamp => stamp.MachineName == row.GetField("#P_USR_CR_Status"));
But this works only if i put [Ignore] attributes on every attribute except "MachineName" in the Stamp model, which is a bad if want to import Stamps from a different CSV later on.
So i tried to define these ignores in the classmap like:
classMap.Map(requestMonitoring => requestMonitoring.PUsrCrStatus.Weight).Ignore();
and tried also:
classMap.Map(typeof(Stamp),typeof(Stamp).GetProperties().SingleOrDefault(p => p.Name == "Id") ).Ignore();
but they both didn't work, it still tells me that no column with name "Weight" is there in the CSV.
Can anyone please help me to get this working? Thanks in advance
I maybe understand what you are trying to do. You might want to rethink the var classMap = csv.Configuration.AutoMap<RequestMonitoring>();
you had in your other question if the only field you want to map in the Stamp
class is MachineName
. AutoMap
is mapping all the properties of PUsrCrStatus
. See if this gets you closer to what you are trying to do.
static void Main(string[] args)
{
using (var stream = new MemoryStream())
using (var writer = new StreamWriter(stream))
using (var reader = new StreamReader(stream))
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
writer.WriteLine("$P_NDS_PN,#P_USR_CR_Status");
writer.WriteLine("test,StampName");
writer.Flush();
stream.Position = 0;
var classMap = new DefaultClassMap<RequestMonitoring>();
foreach (var property in typeof(RequestMonitoring).GetProperties())
{
if (property.Name == "PUsrCrStatus") { continue; }
var columnName = property.Name switch
{
"PNdsPn" => "$P_NDS_PN",
{ } x when x.StartsWith("PUsrCr") => property.Name.Replace("PUsrCr", "#P_USR_CR_"),
_ => property.Name
};
classMap.Map(typeof(RequestMonitoring), property).Name(columnName);
}
classMap.Map(requestMonitoring => requestMonitoring.PUsrCrStatus.MachineName).Name("#P_USR_CR_Status");
csv.Configuration.RegisterClassMap(classMap);
var records = csv.GetRecords<RequestMonitoring>().ToList();
}
}
Or you could use a custom TypeConverter
to map PUsrCrStatus
static void Main(string[] args)
{
using (var stream = new MemoryStream())
using (var writer = new StreamWriter(stream))
using (var reader = new StreamReader(stream))
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
writer.WriteLine("$P_NDS_PN,#P_USR_CR_Status");
writer.WriteLine("test,StampName");
writer.Flush();
stream.Position = 0;
var classMap = new DefaultClassMap<RequestMonitoring>();
foreach (var property in typeof(RequestMonitoring).GetProperties())
{
var columnName = property.Name switch
{
"PNdsPn" => "$P_NDS_PN",
{ } x when x.StartsWith("PUsrCr") => property.Name.Replace("PUsrCr", "#P_USR_CR_"),
_ => property.Name
};
classMap.Map(typeof(RequestMonitoring), property).Name(columnName);
}
classMap.Map(requestMonitoring => requestMonitoring.PUsrCrStatus).TypeConverter<StampTypeConverter>();
csv.Configuration.RegisterClassMap(classMap);
var records = csv.GetRecords<RequestMonitoring>().ToList();
}
}
public class StampTypeConverter : DefaultTypeConverter
{
public override object ConvertFromString(string text, IReaderRow row, MemberMapData memberMapData)
{
return new Stamp { MachineName = text };
}
}