csvhelper IsHeaderCaseSensitive Work around - c#

I'm trying to read in a csv file with a Header 'EMAIL', however, I keep getting the CsvMissingFieldException thrown "Fields 'Email' do not exist in the CSV file".
I set up the CSVreader to handle-
csvReader.Configuration.IsHeaderCaseSensitive = false;
but I'm still getting the same issue. Does anyone know a work around? Or why the configuration isn't working?
In my Utilities class:
public static IEnumerable<T> CSVreader<T>(string fileName)
{
using (var fileReader = File.OpenText(fileName))
using (var csvReader = new CsvHelper.CsvReader(fileReader))
{
csvReader.Configuration.IsHeaderCaseSensitive = false;
csvReader.Configuration.RegisterClassMap<OptOutClassMap>();
while (csvReader.Read())
{
var record = csvReader.GetRecord<T>();
yield return record;
}
}
}
In my Class Map Class:
public string Email { get; set; }
public class CustomClassMap : CsvHelper.Configuration.CsvClassMap<CustomMap>
{
public override void CreateMap()
{
Map(m => m.Email);
}
}

It looks like you are not using the correct ClassMap. From your code above, the line:
csvReader.Configuration.RegisterClassMap<OptOutClassMap>();
should be:
csvReader.Configuration.RegisterClassMap<CustomClassMap>();
Your code when modified works as expected.
static void Main(string[] args)
{
var records = CSVreader<Record>("TextFile1.csv");
}
public class Record
{
public string Email { get; set; }
}
public class CustomClassMap : CsvHelper.Configuration.CsvClassMap<Record>
{
public override void CreateMap()
{
Map(m => m.Email);
}
}
public static IEnumerable<T> CSVreader<T>(string fileName)
{
using (var fileReader = File.OpenText(fileName))
using (var csvReader = new CsvHelper.CsvReader(fileReader))
{
csvReader.Configuration.IsHeaderCaseSensitive = false;
csvReader.Configuration.RegisterClassMap<CustomClassMap>();
while (csvReader.Read())
{
var record = csvReader.GetRecord<T>();
yield return record;
}
}
}

Related

Entity Framework SQLite can't retrieve related object

I'm trying to recreate the sticky notes app in windows 10 using WPF.
I am using Entity Framework with an SQLite database. And EF can't retrieve an object which is the child of another. How can I do that?
I have basically 2 classes i wanna store in this database
StickyNote and SitckyNoteGroup. Each StickyNote has a StickyNoteGroup.
In order you to fully understand I'll post all the classes involved in my problem but here is the github repo if you want https://github.com/Kamigoro/StickyNotes.
namespace Todo.Models
{
public class StickyNote
{
public int Id { get; set; }
public string Name { get; set; }
public string Text { get; set; }
public StickyNoteGroup Group { get; set; }
public override string ToString()
{
return $"Name : {Name}\nText : {Text}";
}
}
}
namespace Todo.Models
{
public class StickyNoteGroup
{
public int Id { get; set; }
public string Name { get; set; }
public string Color { get; set; }
public override string ToString()
{
return $"Name : {Name}\nColor : {Color}";
}
}
}
My class using EntityFramework looks like this and is called NoteContext
using Microsoft.EntityFrameworkCore;
namespace Todo.Models.DataAccess
{
public class NoteContext : DbContext
{
public DbSet<StickyNote> Notes { get; set; }
public DbSet<StickyNoteGroup> NoteGroups { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder options)
=> options.UseSqlite("Data Source=Todo.db");
}
}
And finally the class that I use to do CRUD operations is called DataAccessor and looks like this.
namespace Todo.Models.DataAccess
{
public static class DataAccessor
{
public static List<StickyNote> GetStickyNotes()
{
List<StickyNote> notes;
using (var database = new NoteContext())
{
notes = database.Notes.ToList();
}
return notes;
}
public static void SaveStickyNote(StickyNote stickyNote)
{
using (var database = new NoteContext())
{
database.Notes.Add(stickyNote);
database.SaveChanges();
}
}
public static List<StickyNoteGroup> GetStickyNoteGroups()
{
List<StickyNoteGroup> noteGroups;
using (var database = new NoteContext())
{
noteGroups = database.NoteGroups.ToList();
}
return noteGroups;
}
public static void SaveStickyNoteGroup(StickyNoteGroup stickyNoteGroup)
{
using (var database = new NoteContext())
{
database.NoteGroups.Add(stickyNoteGroup);
database.SaveChanges();
}
}
}
}
My question is why this part of code tell me that there is no StickyNoteGroup for the current StickyNote, even though there is one in the sqlite database?
private void btnAddStickyNote_Click(object sender, RoutedEventArgs e)
{
StickyNoteGroup group = new StickyNoteGroup() { Name = "Test Group", Color = "Red" };
StickyNote note = new StickyNote() { Name = "Note 1", Text = "An attempt to write a note", Group = group };
DataAccessor.SaveStickyNote(note);
foreach (StickyNote currentNote in DataAccessor.GetStickyNotes())
{
Debug.WriteLine(currentNote.Group.ToString());
}
}
StickyNote Table:
StickyNoteGroup Table:
Thanks a lot for your answers. And if you have other comments to do on my code, they are welcomed, because i don't really know the good patterns to work with an ORM like that.
It seems that you need to add Include call:
public static List<StickyNote> GetStickyNotes()
{
List<StickyNote> notes;
using (var database = new NoteContext())
{
notes = database.Notes
.Include(n => n.Group)
.ToList();
}
return notes;
}
BTW you can return evaluated query result data (for example via ToList, ToArray, First and so on) from inside using statement:
public static List<StickyNote> GetStickyNotes()
{
using (var database = new NoteContext())
{
return database.Notes
.Include(n => n.Group)
.ToList();
}
}

Getting error "CS1579: foreach statement cannot operate on variables of type 'ReadJson'" when using foreach loop to read and display JSON file

Trying to iterate over JSON file using foreach loop statement but seem to be getting the below error
CS1579 foreach statement cannot operate on variables of type 'ReadJson' because 'ReadJson' does not contain a public instance definition for 'GetEnumerator'
Get code here:
https://dotnetfiddle.net/y1Q1Cn
using System;
using System.IO;
using System.Globalization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
public partial class ReadJson
{
[JsonProperty("items")]
public Item[] Items { get; set; }
}
public partial class Item
{
[JsonProperty("url")]
public Uri Url { get; set; }
[JsonProperty("item_xpath", NullValueHandling = NullValueHandling.Ignore)]
public string ItemXpath { get; set; }
[JsonProperty("item_size")]
public string ItemSize { get; set; }
}
public partial class ReadJson
{
public static ReadJson FromJson(string json) { return JsonConvert.DeserializeObject<ReadJson>(json, Converter.Settings); }
}
public static class Serialize
{
public static string ToJson(this ReadJson self) { return JsonConvert.SerializeObject(self, Converter.Settings); }
}
internal static class Converter
{
public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
{
MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
DateParseHandling = DateParseHandling.None,
Converters =
{
new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
},
};
}
class UseJsonInVar
{
public static void Test()
{
string filepath = "Question__55692935.json";
File.WriteAllText(filepath, GetJson());
StreamReader ddd = new StreamReader(filepath);
var json = ddd.ReadToEnd();
var objectJson = JsonConvert.DeserializeObject<ReadJson>(json);
foreach (var item in objectJson)
{
var url = objectJson.Items[0].Url;
var user = objectJson.Items[0].ItemXpath;
var pass = objectJson.Items[0].ItemSize;
Console.WriteLine("{0}\n {1}\n {2}", url, user, pass);
}
}
static string GetJson()
{
var json = #"{
""items"":[
{
""url"":""https://www.nordstromrack.com/shop/Women/Clothing/Activewear/Jackets%20&%20Hoodies"",
""item_xpath"":""//*[#href='/shop/product/2299794/nike-vintage-drawstring-hoodie?color=BLACK%2FSAIL']"",
""item_size"":""//*[#href='?color=TRUBER%2FSAIL&size=L']""
},
{
""url"":""https://www.nordstromrack.com/events/281375/products/2584102/j-crew-cotton-cardigan?color=BLACK"",
""item_xpath"":""//*[#href='/events/281375/products/2584102/j-crew-cotton-cardigan?color=BLACK']"",
""item_size"":""//*[#href='?color=BLACK&size=M']""
}
]
}
";
return json;
}
}
public class Program
{
public static void Main()
{
try
{
UseJsonInVar.Test();
}
catch (Exception ex)
{
Console.WriteLine("Failed with unhandled exception: ");
Console.WriteLine(ex);
throw;
}
}
}
You can't enumerate over ReadJson in a foreach because it doesn't implement the GetEnumerator method.
I think what you want to do is enumerate over ReadJson's Items member like so:
var objectJson = JsonConvert.DeserializeObject<ReadJson>(json);
foreach (var item in objectJson.Items)
{
var url = item.Url;
var user = item.ItemXpath;
var pass = item.ItemSize;
Console.WriteLine("{0}\n {1}\n {2}", url, user, pass);
}

Protobuf-net: jagged arrays with wrapper

I know that protobuf-net doesn't support a jagged array and a wrapper is a workaround. I've tried to test it, serialization works fine, but deserialization does nothing, i.e. no error, after deserialization the objects are empty.
[ProtoContract(ImplicitFields = ImplicitFields.AllPublic)]
public class Source
{
public Source()
{
List = new List<Dictionary<string, Item>>();
}
[ProtoIgnore]
public List<Dictionary<string, Item>> List { get; set; }
public List<DictionaryWrapper<string, Item>> ListProto
{
get
{
return List.ConvertAll(x => new DictionaryWrapper<string, Item>(x));
}
set
{
List = value.ConvertAll(x => x.Dictionary);
}
}
}
[ProtoContract(ImplicitFields = ImplicitFields.AllPublic)]
public class Item
{
public string Value { get; set; }
}
[ProtoContract(ImplicitFields = ImplicitFields.AllPublic)]
public sealed class DictionaryWrapper<TKey, TValue>
{
public DictionaryWrapper()
{
}
public DictionaryWrapper(Dictionary<TKey, TValue> value)
{
Dictionary = value;
}
public Dictionary<TKey, TValue> Dictionary { get; set; }
}
serialization method
public void Test()
{
byte[] data = null;
try
{
var source = new Source();
for (var i = 0; i < 5; i++)
{
source.List.Add(new Dictionary<string, Item> {{i.ToString(), new Item {Value = i.ToString()}}});
}
using (var stream = new MemoryStream())
{
Serializer.Serialize(stream, source);
data = stream.ToArray();
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
Source result;
using (var stream = new MemoryStream(data))
{
result = Serializer.Deserialize<Source>(stream);
}
Console.WriteLine(result.List.Count);
}
UPDATE: I've found a workaround. So this fixes the deserialization, still, don't know why ListProto set was not called.
[ProtoBeforeSerialization]
public void ProtoBeforeSerialization()
{
List1Proto = List1.ConvertAll(x => new DictionaryWrapper<string, Item>(x));
}
[ProtoAfterDeserialization]
public void ProtoAfterDeserialization()
{
List1 = List1Proto.ConvertAll(x => x.Dictionary);
}

DataContractSerializer compatibility after namespace changed

I have a class need to be serialized.
namespace serializedobject
{
[DataContract]
public class Class1
{
string string1_;
string string2_;
EntityA entity_;
[DataMember]
public string string3
{
get { return string1_; }
set { string1_ = value; }
}
[DataMember]
public string string2
{
get { return string2_; }
set { string2_ = value; }
}
[DataMember]
public EntityA Entity
{
get { return entity_; }
set { entity_ = value; }
}
public static Class1 FromXML(string desc)
{
using (MemoryStream ms = new MemoryStream())
{
StreamWriter writer = new StreamWriter(ms);
writer.Write(desc);
writer.Flush();
ms.Seek(0, 0);
DataContractSerializer ser = new DataContractSerializer(typeof(Class1));
return (Class1)ser.ReadObject(ms);
}
}
public string ToXML()
{
using (MemoryStream ms = new MemoryStream())
{
DataContractSerializer ser = new DataContractSerializer(typeof(Class1));
ser.WriteObject(ms, this);
ms.Seek(0, 0);
StreamReader reader = new StreamReader(ms);
return reader.ReadToEnd();
}
}
}
[DataContract]
public class EntityA
{
string name_;
[DataMember]
public string Name
{
get { return name_; }
set { name_ = value; }
}
}
}
it is works fine with FromXML and ToXML. one of serialized context like:
<Class1 xmlns="http://schemas.datacontract.org/2004/07/serializedobject" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><Entity><Name>az</Name></Entity><string2 i:nil="true"/><string3>test</string3></Class1>
Later I need to move class EntityA to another namespace "outside", now the serialized context like:
<Class1 xmlns="http://schemas.datacontract.org/2004/07/serializedobject" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><Entity xmlns:a="http://schemas.datacontract.org/2004/07/outside"><a:Name>az</a:Name></Entity><string2 i:nil="true"/><string3>test</string3></Class1>
but now the serialized xml which created before change namespace can't be deserialized correctly. I guess this is because of for class "EntityA" changed namespace (xmlns:a added).
does anybody run into the problem before? any suggestion?
You can stop the namespace being added to the XML by specifying [DataContract(Namespace="")]. This relies on you setting that attribute BEFORE you save any xml code.
You can use this approach only if you have not already serialized any data, so this is the approach you would use when first designing a class to be serialized.
(If you have already got serialized data that you must deal with, see the second part of my answer below.)
This code sample has the two classes called Demo in two different namespaces, Test1 and Test2.
We serialize the code using the class from one namespace, and deserialize it using the class from the other namespace:
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Xml;
namespace ConsoleApp1
{
namespace Test1
{
[DataContract(Namespace="")]
public sealed class Demo
{
[DataMember]
public string Value { get; set; }
}
}
namespace Test2
{
[DataContract(Namespace="")]
public sealed class Demo
{
[DataMember]
public string Value { get; set; }
}
}
sealed class Program
{
private void run()
{
string filename = Path.GetTempFileName();
var demo1 = new Test1.Demo {Value = "DEMO"};
ToFile(filename, demo1);
var demo2 = FromFile<Test2.Demo>(filename);
Console.WriteLine(demo2.Value);
}
public static void ToFile(string filename, object obj)
{
DataContractSerializer serializer = new DataContractSerializer(obj.GetType());
using (var streamWriter = File.CreateText(filename))
using (var xmlWriter = XmlWriter.Create(streamWriter, new XmlWriterSettings{Indent = true}))
{
serializer.WriteObject(xmlWriter, obj);
}
}
public static T FromFile<T>(string filename)
{
DataContractSerializer serializer = new DataContractSerializer(typeof(T));
using (var textReader = File.OpenText(filename))
using (var xmlReader = XmlReader.Create(textReader))
{
return (T)serializer.ReadObject(xmlReader);
}
}
[STAThread]
static void Main(string[] args)
{
new Program().run();
}
}
}
If you have already serialized data without the Namespace="" attribute, then you will need instead to apply the appropriate namespace to the new class:
namespace Test1
{
[DataContract]
public sealed class Demo
{
[DataMember]
public string Value { get; set; }
}
}
namespace Test2
{
// Note the namespace includes both nested namespaces, i.e. ConsoleApp1.Test1
[DataContract(Namespace="http://schemas.datacontract.org/2004/07/ConsoleApp1.Test1")]
public sealed class Demo
{
[DataMember]
public string Value { get; set; }
}
}

How do I find out which images are where in a PDF?

I am using ITextSharp trying to parse a PDF I have no control over. It doesn't use AcroForm, but it does use images of checkboxes. I can find and extract the two checkbox images themselves (checked and unchecked), but I cannot figure out how to get the references to those images.
How do I find out how many times each image is referenced, and where that reference is placed?
I found a way to get what I needed via the IRenderListener, starting with this comment: http://3d.5341.com/list/27/1036159.html
public static void Main()
{
string inputStream = "whatever.pdf";
PdfReader reader = new PdfReader(inputStream);
var parser = new PdfReaderContentParser(reader);
var imgScan = new FormListener();
for (int i=1; i<=reader.NumberOfPages; ++i)
parser.ProcessContent(1, imgScan);
reader.Close();
foreach (var r in imgScan.CheckBoxBoxes)
{
r.Dump();
}
}
public class CheckboxBox
{
public CheckboxBox()
{
this.CheckboxStates = new List<bool>();
}
public string Name { get;set; }
public List<bool> CheckboxStates {get;set;}
}
public class FormListener : IRenderListener
{
public List<CheckboxBox> CheckBoxBoxes { get;set;}
private CheckboxBox m_CurrentCheckboxBox { get;set;}
public FormListener()
{
this.CheckBoxBoxes = new List<CheckboxBox>();
this.BeginNewBox();
}
public void BeginTextBlock() {}
public void EndTextBlock() {}
private void BeginNewBox()
{
this.m_CurrentCheckboxBox = new CheckboxBox();
this.CheckBoxBoxes.Add(this.m_CurrentCheckboxBox);
}
private bool IsNewBoxStarting(TextRenderInfo renderInfo)
{
return Regex.IsMatch(renderInfo.GetText(), #"\d+\.");
}
public void RenderText(TextRenderInfo renderInfo) {
if (this.IsNewBoxStarting(renderInfo))
BeginNewBox();
this.m_CurrentCheckboxBox.Name += renderInfo.GetText() + " ";
}
private bool GetCheckboxState(ImageRenderInfo renderInfo)
{
var n = renderInfo.GetRef().Number;
return n == 21; // MagicNumberOfYesCheckboxImage;
}
public void RenderImage(ImageRenderInfo renderInfo)
{
this.m_CurrentCheckboxBox.CheckboxStates.Add(this.GetCheckboxState(renderInfo));
}
}

Categories