Hi I'm using "CsvHelper" (v 2.16.3), I want to use prefix in my object that will append the child prefix to the parent prefix.
But I didn't manged to do so,
Does CsvJelper support that?
For example:
My Model:
public class ExampleModel
{
public string status { get; set; }
public ExampleModelNode leftNode { get; set; }
public ExampleModelNode rightNode { get; set; }
}
public class ExampleModelNode
{
public string status { get; set; }
public NodeData data { get; set; }
}
public class NodeData
{
public string data { get; set; }
}
My mapping class:
class ExampleModelMap : CsvClassMap<ExampleModel>
{
public ExampleModelMap()
{
Map(m => m.status);
References<ExampleModelNodeMap>(m => m.leftNode).Prefix("Right_");
References<ExampleModelNodeMap>(m => m.rightNode).Prefix("Left_");
}
}
class ExampleModelNodeMap : CsvClassMap<ExampleModelNode>
{
public ExampleModelNodeMap()
{
AutoMap(false,true);
References<NodeDataMap>(m => m.data).Prefix("Data_");
}
}
class NodeDataMap : CsvClassMap<NodeData>
{
public NodeDataMap()
{
AutoMap(false,true);
}
}
Init and running:
ExampleModel exampleModel = new ExampleModel()
{
status = "A",
rightNode = new ExampleModelNode()
{
status = "L",
data = new NodeData()
{
data = "L Data"
}
},
leftNode = new ExampleModelNode()
{
status = "R",
data = new NodeData()
{
data = "R Data"
}
}
};
StringBuilder sb = new StringBuilder();
TextWriter writer = new StringWriter(sb);
var csv = new CsvWriter(writer);
csv.Configuration.RegisterClassMap(new ExampleModelMap());
csv.Configuration.PrefixReferenceHeaders = true;
csv.WriteHeader(typeof(ExampleModel));
csv.WriteRecord(exampleModel);
writer.Flush();
writer.Close();
File.WriteAllText("csv.csv", sb.ToString());
The output is:
But the expected output that I want is:
Does CsvHelper support that? How can I get this mapping?
Related
I am having the below model class CallbackResponse.cs :
public class CallbackResponse
{
public Callback Data { get; set; }
}
public class Callback
{
public IEnumerable<ReviewInProgressActivityFeed> ActivitiesFeed { get; set; }
}
public class ReviewInProgressActivityFeed
{
public ReviewInProgressStatus ReviewerSession { get; set; }
}
public class ReviewInProgressStatus
{
public Guid ReviewActivityId { get; set; }
public string ReviewerName { get; set; }
public string ReviewComments { get; set; }
public DateTime ActivityDateTime { get; set; }
}
Sample Payload:
{
"data":
{
"activitiesFeed": [
{
"reviewerSession":
{
"reviewActivityId": "dd9937c3-7c01-4a4a-bc8d-05ef37b07ee5",
"ReviewerName": "Verification Team",
"reviewComments": "upload business verification document for further verification.",
"activityDateTime": "2021-03-31T18:34:26.5978962Z"
},
},
{
"reviewerSession":
{
"reviewActivityId": "dd9937c3-7c01-4a4a-bc8d-05ef37b07ee5",
"ReviewerName": "Other Team",
"reviewComments": "other documents required for verification.",
"activityDateTime": "2021-03-31T19:34:26.5978962Z"
},
}
]
}
}
I am trying to get the data from DB via the CallbackResponse model class. Please find the code for below.
public async Task<CallbackResponse> CallbackActivityFeedAsync(Guid Id)
{
CallbackResponse containerItems = new CallbackResponse();
IQueryable<HumanReviewRequest> query = cosmosReviewRequestContainer.GetItemLinqQueryable<HumanReviewRequest>(true);
query = query.Where(x => x.id == Id);
FeedIterator<HumanReviewRequest> feedIterator = query.ToFeedIterator();
while (feedIterator.HasMoreResults)
{
FeedResponse<HumanReviewRequest> r = await feedIterator.ReadNextAsync().ConfigureAwait(false);
foreach (HumanReviewRequest requestModel in r)
{
containerItems = new CallbackResponse
{
Data = new Callback
{
ActivitiesFeed = new List<ReviewInProgressActivityFeed>
{
new ReviewInProgressActivityFeed
{
ReviewerSession = new ReviewInProgressStatus
{
ReviewActivityId = requestModel.ReviewActivities.Select(x => x.ReviewerSession.ReviewActivityId).LastOrDefault(),
ActivityDateTime = requestModel.ReviewActivities.Select(x => x.ReviewerSession.ActivityDateTime).LastOrDefault(),
ReviewComments = requestModel.ReviewActivities.Select(x => x.ReviewerSession.ReviewerComments).LastOrDefault(),
ReviewerName = requestModel.ReviewActivities.Select(x => x.ReviewerSession.ReviewerName).LastOrDefault()
}
}
}
}
};
}
}
return containerItems;
}
The Problem here is I could not able to fetch all the records present in activitiesFeed array in DB. Instead I could only able to fetch the last record in that array(I am using Azure Cosmos DB). Please help me in this.
HumanReviewRequest.cs (which is DB Class)for reference:
public class HumanReviewRequest
{
public Guid Id { get; set; }
public IEnumerable<ReviewActivity> ReviewActivities { get; set; }
public class ReviewActivity
{
public ReviewerSession ReviewerSession { get; set; }
public string UserComments { get; set; }
}
public class ReviewerSession
{
public Guid ReviewActivityId { get; set; }
public Guid ReviewerUserId { get; set; }
public DateTime ActivityDateTime { get; set; }
public string ReviewerComments { get; set; }
}
This is because you are creating a new List<ReviewInProgressActivityFeed>, a new ReviewInProgressActivityFeed and reading only the last element in activitiesFeed for each iteration:
ReviewerSession = new ReviewInProgressStatus
{
ReviewActivityId = requestModel.ReviewActivities.Select(x => x.ReviewerSession.ReviewActivityId).LastOrDefault(),
ActivityDateTime = requestModel.ReviewActivities.Select(x => x.ReviewerSession.ActivityDateTime).LastOrDefault(),
ReviewComments = requestModel.ReviewActivities.Select(x => x.ReviewerSession.ReviewerComments).LastOrDefault(),
ReviewerName = requestModel.ReviewActivities.Select(x => x.ReviewerSession.ReviewerName).LastOrDefault()
}
Try below code instead of the above code:
public async Task<CallbackResponse> CallbackActivityFeedAsync(Guid Id)
{
CallbackResponse containerItems = new CallbackResponse();
containerItems.Data = new Callback();
containerItems.Data.ActivitiesFeed = new List<ReviewInProgressActivityFeed>();
IQueryable<HumanReviewRequest> query = cosmosReviewRequestContainer.GetItemLinqQueryable<HumanReviewRequest>(true);
query = query.Where(x => x.id == Id);
FeedIterator<HumanReviewRequest> feedIterator = query.ToFeedIterator();
while (feedIterator.HasMoreResults)
{
FeedResponse<HumanReviewRequest> r = await feedIterator.ReadNextAsync().ConfigureAwait(false);
if (r != null || r.ReviewActivities != null)
{
foreach (HumanReviewRequest requestModel in r.ReviewActivities)
{
containerItems.Data.ActivitiesFeed.Add(
new ReviewInProgressActivityFeed
{
ReviewerSession = new ReviewInProgressStatus
{
ReviewActivityId = requestModel.ReviewerSession.ReviewActivityId,
ActivityDateTime = requestModel.ReviewerSession.ActivityDateTime,
ReviewComments = requestModel.ReviewerSession.ReviewerComments,
ReviewerName = requestModel.ReviewerSession.ReviewerName
}
});
}
}
}
};
}
}
return containerItems;
}
Imagine a collection of EF dbSet like this :
public class Employee {
...
public string FirstName { get; set; }
public List<Badge> Badge { get; set; }
}
public class Badge {
public long CSN { get; set; }
public int EmployeeId { get; set; }
public int Type { get; set; }
}
This models are used in my SGBB and I want to use it to import data from a CSV file. But this file has a small difference. It give only one badge like this :
FIRSTNAME;CSN;TYPE
Jerome;12345;1
I have used a CollectionGenericConverter, to initialize the List with a new record.
Map(m => m.Firstname).Name("Firstname");
Map(m => m.Badges).Name("CSN").TypeConverter<BadgeConverter>();
...
public class BadgeConverter : CollectionGenericConverter {
public override object ConvertFromString(String text, IReaderRow row, MemberMapData memberMapData) {
return new List<Badge> {
new Badge {
CSN = Convert.ToInt16(text)
}
};
}
}
I have just a problem with the second value, using a second converter reset the list of badges :
Map(m => m.Badges).Name("Type").TypeConverter<AnotherOneBadgeConverter>();
And set directly the first item not work :
Map(m => m.Badges[0].Type).Name("Type");
How to do that ?
Something like this may work for you.
public class Program
{
public static void Main(string[] args)
{
using (MemoryStream stream = new MemoryStream())
using (StreamWriter writer = new StreamWriter(stream))
using (StreamReader reader = new StreamReader(stream))
using (CsvReader csv = new CsvReader(reader))
{
writer.WriteLine("FIRSTNAME;CSN;TYPE");
writer.WriteLine("Jerome;12345;1");
writer.Flush();
stream.Position = 0;
csv.Configuration.Delimiter = ";";
csv.Configuration.RegisterClassMap<EmployeeMap>();
var records = csv.GetRecords<Employee>().ToList();
}
}
}
public class Employee
{
public string FirstName { get; set; }
public List<Badge> Badge { get; set; }
}
public class Badge
{
public long CSN { get; set; }
public int EmployeeId { get; set; }
public int Type { get; set; }
}
public class EmployeeMap: ClassMap<Employee>
{
public EmployeeMap()
{
Map(m => m.FirstName).Name("FIRSTNAME");
Map(m => m.Badge).ConvertUsing(row =>
{
var list = new List<Badge>
{
new Badge { CSN = row.GetField<long>("CSN"), Type = row.GetField<int>("TYPE") },
};
return list;
});
}
}
I use AutoMapper 8.1.0 in a asp.net core project. I have an Automapper mapping that doesn't work as I expected. I reproduced the configuration so you can test it by yourself. So I have an ExpenseReport with a collection of ExpenseReportItem and this one with another collection. I have to keep the data of eTaxCollection after the mapping, but they are lost in the process.
So the question is why values of eTaxCollections are lost after calling _mapper.Map(vmodel, model) and how can I keep them?
The ignore attribute don't work. I also tried UseDestinationValue(). I lost 2 days trying to figure it out and I'm exhausted.
public void WeatherForecasts()
{
int[] excludeTaxes = new int[] { 2 };
var vmodel = new ExpenseReportCreateEditModel();
vmodel.Expenses.Add(new ExpenseReportItemModel()
{
ExcludeTaxIds = excludeTaxes,
Total = 12,
Id = 1
});
// fetch from bd
var model = new ExpenseReport();
// values will be lost after _mapper.Map...
var eTaxCollections = new HashSet<ExcludeExpenseReportItemTax>();
eTaxCollections.Add(new ExcludeExpenseReportItemTax()
{
TaxId = 1,
ExpenseReportItemId = 1
});
model.Items.Add(new ExpenseReportItem()
{
ExcludeTaxes = eTaxCollections,
ExpenseReportId = 1,
Id = 9
});
_mapper.Map(vmodel, model);
}
public class ExpenseReportCreateEditModelProfile : Profile
{
public ExpenseReportCreateEditModelProfile()
{
CreateMap<ExpenseReportCreateEditModel, ExpenseReport>()
.ForMember(d => d.Items, s => s.MapFrom(m => m.Expenses));
}
}
public class ExpenseReportItemModelProfile : Profile
{
public ExpenseReportItemModelProfile()
{
CreateMap<ExpenseReportItemModel, ExpenseReportItem>()
.ForMember(d => d.ExcludeTaxes, s => s.Ignore()); // <<<==== data are lost
}
}
public class ExpenseReportCreateEditModel
{
public int Id { get; set; }
public ICollection<ExpenseReportItemModel> Expenses { get; set; }
public ExpenseReportCreateEditModel()
{
Expenses = new HashSet<ExpenseReportItemModel>();
}
}
public class ExpenseReportItemModel
{
public int Id { get; set; }
public ICollection<int> ExcludeTaxIds { get; set; }
public decimal Total { get; set; }
public ExpenseReportItemModel()
{
ExcludeTaxIds = new HashSet<int>();
}
}
public class ExpenseReport
{
public int Id { get; set; }
public virtual ICollection<ExpenseReportItem> Items { get; set; }
public ExpenseReport()
{
Items = new HashSet<ExpenseReportItem>();
}
}
public class ExpenseReportItem
{
public int Id { get; set; }
public int ExpenseReportId { get; set; }
public virtual ICollection<ExcludeExpenseReportItemTax> ExcludeTaxes { get; set; }
public ExpenseReportItem()
{
ExcludeTaxes = new HashSet<ExcludeExpenseReportItemTax>();
}
}
public class ExcludeExpenseReportItemTax
{
public int ExpenseReportItemId { get; set; }
public virtual ExpenseReportItem ExpenseReportItem { get; set; }
public int TaxId { get; set; }
}
Thank you for any help
Edit
I execute the execution plan and perhaps this is the problem:
$typeMapDestination = ($dest ?? .New WebApplication1.Controllers.SampleDataController+ExpenseReportItem());
This is only way I can lost the values.
I have to find a solution now
Here the complete execution plan :
.If ($src == null) {
.Default(WebApplication1.Controllers.SampleDataController+ExpenseReportItem)
} .Else {
.Block() {
$typeMapDestination = ($dest ?? .New WebApplication1.Controllers.SampleDataController+ExpenseReportItem());
.Try {
.Block(System.Int32 $resolvedValue) {
.Block() {
$resolvedValue = .If (
$src == null || False
) {
.Default(System.Int32)
} .Else {
$src.Id
};
$typeMapDestination.Id = $resolvedValue
}
}
} .Catch (System.Exception $ex) {
.Block() {
.Throw .New AutoMapper.AutoMapperMappingException(
"Error mapping types.",
$ex,
.Constant<AutoMapper.TypePair>(AutoMapper.TypePair),
.Constant<AutoMapper.TypeMap>(AutoMapper.TypeMap),
.Constant<AutoMapper.PropertyMap>(AutoMapper.PropertyMap));
.Default(System.Int32)
}
};
$typeMapDestination
}
}
I want to write my items by JSON format, but My files empty. Here is my two class:
public class DocPart
{
public string Title { get; set; }
public bool Checked { get; set; }
}
public class DocConfig
{
public List<DocPart> Parts { get; set; }
public static DocConfig LoadFromString(string jsonData)
{
var config = new DocConfig();
config.Parts = new List<DocPart>();
var part = new DocPart
{
Title = "chapter1",
"chapter2",
Checked = checkBox1.Checked,
checkbox2.Checked
};
config.Parts.Add(part);
var configString = config.SaveToString();
File.WriteAllText(#"C:\link to my file", configString);
var configString = File.ReadAllText(#"C:\link to my file");
var config = DocConfig.LoadFromString(configString);
foreach (var part in config.Parts)
{
if (part.Title == "chapter1")
chekbox1.Checked = part.Checked;
if (part.Title == "chapter2")
checkbox2.Checked = part.Checked;
var serializer = new DataContractJsonSerializer(typeof(DocConfig));
var ms = new MemoryStream(Encoding.UTF8.GetBytes(jsonData));
var config = (DocConfig)serializer.ReadObject(ms);
return config;
}
}
public string SaveToString()
{
var serializer = new DataContractJsonSerializer(typeof(DocConfig));
var ms = new MemoryStream();
serializer.WriteObject(ms, this);
return Encoding.UTF8.GetString(ms.ToArray());
}
}
So I run my program, everything looks okey, but my file is still empty without any JSON format data. Maybe you could help me?
Thanks.
public class DocPart
{
public string Title { get; set; }
public bool Checked { get; set; }
}
public class DocConfig
{
public List<DocPart> Parts { get; set; }
public static DocConfig LoadFromString()
{
var config = new DocConfig();
config.Parts = new List<DocPart>();
var part1 = new DocPart
{
Title = "chapter1",
Checked = checkBox1.Checked
};
config.Parts.Add(part1);
var part2 = new DocPart
{
Title = "chapter2",
Checked = checkBox2.Checked
};
config.Parts.Add(part2);
var configString = config.SaveToString();
File.WriteAllText(#"d:\temp\test.json", configString);
configString = File.ReadAllText(#"d:\temp\test.json");
var ms = new MemoryStream(Encoding.UTF8.GetBytes(configString));
var serializer = new DataContractJsonSerializer(typeof(DocConfig));
config = (DocConfig)serializer.ReadObject(ms);
foreach (var part in config.Parts)
{
if (part.Title == "chapter1")
{
chekbox1.Checked = part.Checked;
Debug.WriteLine("chapter1" + part.Checked);
}
if (part.Title == "chapter2")
{
checkbox2.Checked = part.Checked;
Debug.WriteLine("chapter2" + part.Checked);
}
}
return config;
}
public string SaveToString()
{
var serializer = new DataContractJsonSerializer(typeof(DocConfig));
var ms = new MemoryStream();
serializer.WriteObject(ms, this);
return Encoding.UTF8.GetString(ms.ToArray());
}
}
Here's a really simple example I mocked up for you...
void Main()
{
const string filePath = #"C:\FilePath\json.txt";
const string testJson = #"{""glossary"": {""title"": ""example glossary"", ""GlossDiv"": {""title"": ""S"", ""GlossList"": {""GlossEntry"": {""ID"": ""SGML"", ""SortAs"": ""SGML"", ""GlossTerm"": ""Standard Generalized Markup Language"", ""Acronym"": ""SGML"", ""Abbrev"": ""ISO 8879:1986"", ""GlossDef"": {""para"": ""A meta-markup language, used to create markup languages such as DocBook."", ""GlossSeeAlso"": [""GML"", ""XML""]}, ""GlossSee"": ""markup""}}}}}";
// Now we have our Json Object...
SampleJson sample = JsonConvert.DeserializeObject<SampleJson>(testJson);
// We convert it back into a string with indentation...
string jsonString = JsonConvert.SerializeObject(sample, Newtonsoft.Json.Formatting.Indented);
// Now simply save to file...
using (StreamWriter writer = new StreamWriter(filePath))
{
writer.WriteLine(jsonString);
}
Process.Start(filePath);
}
// The following classes are what the `testJson` string is deserialized into.
public class GlossDef
{
[JsonProperty("para")]
public string Para { get; set; }
[JsonProperty("GlossSeeAlso")]
public string[] GlossSeeAlso { get; set; }
}
public class GlossEntry
{
[JsonProperty("ID")]
public string ID { get; set; }
[JsonProperty("SortAs")]
public string SortAs { get; set; }
[JsonProperty("GlossTerm")]
public string GlossTerm { get; set; }
[JsonProperty("Acronym")]
public string Acronym { get; set; }
[JsonProperty("Abbrev")]
public string Abbrev { get; set; }
[JsonProperty("GlossDef")]
public GlossDef GlossDef { get; set; }
[JsonProperty("GlossSee")]
public string GlossSee { get; set; }
}
public class GlossList
{
[JsonProperty("GlossEntry")]
public GlossEntry GlossEntry { get; set; }
}
public class GlossDiv
{
[JsonProperty("title")]
public string Title { get; set; }
[JsonProperty("GlossList")]
public GlossList GlossList { get; set; }
}
public class Glossary
{
[JsonProperty("title")]
public string Title { get; set; }
[JsonProperty("GlossDiv")]
public GlossDiv GlossDiv { get; set; }
}
public class SampleJson
{
[JsonProperty("glossary")]
public Glossary Glossary { get; set; }
}
Below codes run perfectly but i want to re generate simply
static void YeniMethodListele()
{
Calısan calisan = new Calısan(){ ID=1, Ad="xxx", SoyAd="yyy"};
List<Calısan> myList = new List<Calısan>();
myList.Add(calisan);
MyCalısan myCalısan = new MyCalısan() { list = myList };
//myCalısan.list.Add(calisan);
foreach (Calısan item in myCalısan.list)
{
Console.WriteLine(item.Ad.ToString());
}
}
}
public class Calısan
{
public int ID { get; set; }
public string Ad { get; set; }
public string SoyAd { get; set; }
}
public class MyCalısan
{
public List<Calısan> list { get; set; }
public MyCalısan()
{
list = new List<Calısan>();
}
}
Here is a sample of a couple of ways to create the list a little more simply. Note the small change to the Calısan object to give it a default constructor and an overloaded constructor.
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
////Calısan calisan = new Calısan() { ID = 1, Ad = "xxx", SoyAd = "yyy" };
MyCalısan myCalısan = new MyCalısan();
//option 1:
//==========
myCalısan.list.AddRange(new[] { new Calısan() { ID = 1, Ad = "xxx", SoyAd = "yyyy" }, new Calısan() { ID = 2, Ad = "blah", SoyAd = "jiggy" } });
//option 2:
//=========
myCalısan.list.AddRange(new[] { new Calısan(1, "xxx", "yyy"), new Calısan(2, "blah", "jiggy") });
////myCalısan.list.Add(calisan);
foreach (Calısan item in myCalısan.list)
{
Console.WriteLine(item.Ad.ToString());
}
Console.ReadKey();
}
}
public class Calısan
{
public Calısan() { }
public Calısan(int id, string ad, string soyad)
{
ID = id;
Ad = ad;
SoyAd = soyad;
}
public int ID { get; set; }
public string Ad { get; set; }
public string SoyAd { get; set; }
}
public class MyCalısan
{
public List<Calısan> list { get; set; }
public MyCalısan()
{
list = new List<Calısan>();
}
}
}