Problems with converting FixedLength format to to csv using same class definition - filehelpers

I defined both FixedLength and Delimited attributes on a single class. It reads the fixed length file fine but fails when i try to write out a csv.
[FixedLengthRecord]
[DelimitedRecord(",")]
public class PCFFileHeader
{
[FieldFixedLength(2)] public string RecordType { get; set; }
[FieldFixedLength(25)] public string FileDescription { get; set; }
}
var engine = new MultiRecordEngine(typeof(PCFFileHeader), typeof(SecondHeader));
engine.RecordSelector = RecordSelector;
var output = engine.ReadFile(filePath);
// code to extract PCFHeader from output and create a list
var headerEngine = new DelimitedFileEngine<PCFFileHeader>();
headerEngine.WriteFile("header_" + DateTime.Now.ToString("yyyyMMddhhmmss"), pcfFileHeaderList);

You can't add both [FixedLengthRecord] and [DelimitedRecord] to the same class. FileHelpers will just treat it as [FixedLengthRecord]. With your current class, it will error if you do:
// This causes an exception because the class is not a delimited record definition
var delimitedHeaderEngine = new DelimitedFileEngine<PCFFileHeader>();
Instead, you should have two PCFFileHeader definitions, FixedPCFFileHeader and DelimitedPCFFileHeader.
[FixedLengthRecord]
public class FixedPCFFileHeader
{
[FieldFixedLength(2)] public string RecordType { get; set; }
[FieldFixedLength(25)] public string FileDescription { get; set; }
}
[DelimitedRecord(",")]
public class DelimitedPCFFileHeader
{
public string RecordType { get; set; }
public string FileDescription { get; set; }
}
class Program
{
static void Main(string[] args)
{
var fixedHeaderEngine = new FileHelperEngine<FixedPCFFileHeader>();
var recordsFixed = fixedHeaderEngine.ReadString("AADescription ");
Debug.Assert(recordsFixed.Count() == 1);
Debug.Assert(recordsFixed[0].RecordType == "AA");
Debug.Assert(recordsFixed[0].FileDescription == "Description ");
var delimitedHeaderEngine = new FileHelperEngine<DelimitedPCFFileHeader>();
var recordsDelimited = delimitedHeaderEngine.ReadString("AA,Description");
Debug.Assert(recordsDelimited.Count() == 1);
Debug.Assert(recordsDelimited[0].RecordType == "AA");
Debug.Assert(recordsDelimited[0].FileDescription == "Description");
var pcfFileHeaderList = new FixedPCFFileHeader[] { new FixedPCFFileHeader() { RecordType = "AA", FileDescription = "Description" } };
// If you want to output a header when exporting uncomment the following
//headerEngine.HeaderText = "header_" + DateTime.Now.ToString("yyyyMMddhhmmss");
var output = fixedHeaderEngine.WriteString(pcfFileHeaderList);
Debug.Assert(output == "AADescription \r\n");
Console.WriteLine("All OK");
Console.ReadLine();
}
}
If you want to automatically detect the correct format during import, you can use the FileHelpers Smart Format Detector.

Related

is there a reason to serialize and then deserialize an object?

I have a SOAP web service that someone developed at my work place and i try to learn it and i came across a move in the code that i can't get my head around. can someone explain to me the logic behind it? why would someone want to serialize an object and a line after to deserialize it?
**this is the whole code: if someone has a way to improve the code it will be appreciated: **
using IRail.BLL.SAP;
using IRail.Entities.SAP.Report;
using IRail.WebAPI.Heplers;
using Logger;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Web.Script.Serialization;
using System.Web.Services;
namespace IRail.WebAPI
{
public class EventInfo
{
public string QMNUM { get; set; }
public string QMART { get; set; }
public string STATUS { get; set; }
public string MAHUT_CODE { get; set; }
public string MAHUT_TXT { get; set; }
public string START_DATE { get; set; }
public string START_TIME { get; set; }
public string END_DATE { get; set; }
public string END_TIME { get; set; }
public string ZQMNUM { get; set; }
public string QMTXT { get; set; }
public string IKUN { get; set; }
public string ZLONG { get; set; }
public string LAT { get; set; }
public string TPLNR { get; set; }
public string ZZKM_NUM { get; set; }
public string ZZTOKM_NUM { get; set; }
}
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
[System.Web.Script.Services.ScriptService]
public class Events : System.Web.Services.WebService
{
public static readonly ILogger _logger = LogManager.GetLogger();
[WebMethod]
public string UpdateEvent(EventInfo eventInfo)
{
// create an instance of SapClient object an fill it with the input parameters,
// that passes by the url to the function using the eventInfo class.
SapClient SapArgs = new SapClient()
{
params_input = "",
QNUM = eventInfo.QMNUM,
QMART = eventInfo.QMART,
STATUS = eventInfo.STATUS,
MAHUT_CODE = eventInfo.MAHUT_CODE,
MAHUT_TXT = eventInfo.MAHUT_TXT,
START_DATE = eventInfo.START_DATE,
START_TIME = eventInfo.START_TIME,
END_DATE = eventInfo.END_DATE,
END_TIME = eventInfo.END_TIME,
ZQMNUM = eventInfo.ZQMNUM,
QMTXT = eventInfo.QMTXT,
IKUN = eventInfo.IKUN,
ZLONG = eventInfo.ZLONG,
LAT = eventInfo.LAT,
TPLNR = eventInfo.TPLNR,
ZZKM_NUM = eventInfo.ZZKM_NUM,
ZZTOKM_NUM = eventInfo.ZZTOKM_NUM,
ikunx = "",
ikuny = "",
operation_type = "",
returnZ = "",
returnM = "",
returnTrueCurves = "",
f = ""
};
string errorMsg = String.Empty;
string outputJson = String.Empty;
ApiHelper apiHelper = new ApiHelper();
try
{
// create an instance of JS Serializer.
var jss = new JavaScriptSerializer();
// serialize the object to convert it to json format.
JObject sapArgs = JObject.Parse(jss.Serialize(SapArgs));
// decerialize the object back from json format to pass the JSON string representation
// of the sapArgs object as the input to the callGPAsync method.
var dict = jss.Deserialize<Dictionary<string, string>>(sapArgs.ToString());
// create an instance of EventsEngine.
EventsEngine eventsEngine = new EventsEngine();
// assign the type of the event to the events object:
// check the event type.
SapArgs.operation_type = eventsEngine.CheckEventType(dict, ref errorMsg);
// assign the event type that has returned to the sapArgs object's operation_type parameter.
sapArgs["operation_type"] = SapArgs.operation_type; // "1";// set operation_type for test;
// if encountered an error return the content of it.
if (errorMsg != "") return "UpdateEvent ERROR: " + errorMsg;
_logger.Info($"Username: {Utils.GetUserName()}, UpdateEvent : {sapArgs.ToString()}, eventType :{SapArgs.operation_type}");
if (!string.IsNullOrWhiteSpace(apiHelper.getValueFromDict(dict, "IKUN")) && dict["IKUN"].ToString() == "Y")
{
var res = apiHelper.convertCoordiateWGSToITM(sapArgs).GetAwaiter().GetResult();
}
outputJson = apiHelper.callGPAsync(sapArgs).GetAwaiter().GetResult();
try
{
// if there is result from submitted job add operation_type
outputJson = outputJson.Replace("}", ", \"operation_type\" = \"" + SapArgs.operation_type + "\" }");
}
catch (Exception outputEx)
{
return "outputJson ERROR: " + outputEx;
}
var response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content = new StringContent(outputJson, System.Text.Encoding.UTF8, "application/json");
return outputJson;
}
catch (Exception ex)
{
_logger.Error(" UpdateEvent ERROR : " + SapArgs.ToString() + ", eventType :" + SapArgs.operation_type + ", errorMsg :" + errorMsg);
_logger.Error(ex);
return "UpdateEvent ERROR: update failed on exception. please check logs.";
}
//0. check with documentation - what are the parameters - in sap document
//0. log -> input call
//1. properties input validation -
// A. all inputs are correct //2.4 in documents ---> function in BLL that does the validation
//2. if all ok - -- delete prev event
//3. call GP service to update new event
//4. return success + log reult
}
}
}
I did not try anything i just want to understand the logic.

RavenDb changes to Property (nullable) on Entity that is a class doesn't save

I have a class like this:
public class Content {
public string Id {get; set;} = "content/"
public ContentJob? Job {get; set;}
}
public class ContentJob {
public string JobId {get; set;} = string.Empty;
}
I can create the content and if the job is there it will persist. with Store/SaveChanges.
But what I can't do is update (or more accurately set) ContentJob on Content and have it detect that there was a change. (HasChange(instance) == false) and SaveChanges doesn't update the database.
Why? And how do I make it detect the change?
(incidentally I tried using C# 9 records in hopes that because it automatically does deep object equality that this would solve it and no, it doesn't)
I created an unit-test based on your question, and it works as expected.
[Fact]
public void ShouldWork()
{
using (var store = GetDocumentStore())
{
string id = string.Empty;
using (var session = store.OpenSession())
{
var c = new Content();
session.Store(c);
session.SaveChanges();
id = session.Advanced.GetDocumentId(c);
var entity = session.Load<Content>(id);
entity.Job = new ContentJob()
{
JobId = "123"
};
Assert.True(session.Advanced.HasChanged(entity));
session.SaveChanges();
}
Assert.False(string.IsNullOrEmpty(id));
using (var session = store.OpenSession())
{
var entity = session.Load<Content>(id);
Assert.NotNull(entity.Job);
Assert.Equal("123", entity.Job.JobId);
}
}
}
public class Content
{
public string Id { get; set; } = "content/";
public ContentJob? Job { get; set; }
}
public class ContentJob
{
public string JobId { get; set; } = string.Empty;
}

Retrieve values from SQL database - EF

I'm trying to figure out how to pull values from a SQL database and display this in a razor view.
I have the following class using Entity Framework (I believe)
public class EventLog
{
[Key]
public int Id { get; set; }
public int EventId { get; set; }
public int MaxDelegates { get; set; }
public string Code { get; set; }
public DateTime End { get; set; }
public string Title { get; set; }
}
And I want to map title to DBTitle in the following model:
public class CourseDetailVM : CourseDetailSummaryVM
{
public EventLog DBTitle { get; set; }
}
I then want to see this in the following view:
#using TSW.Web.Helpers
#model TSW.Web.ViewModels.CourseDetailVM
#{
Layout = "~/Views/_Master.cshtml";
}
#Model.DBTitle.Title;
I have the following controller already in place (sorry for the length I plan to reduce this down):
public class CourseDetailController : BaseRenderController<CourseDetailPageDT>
{
private readonly ISitePageFactory _pageFactory = null;
private readonly IEventService _eventService = null;
public CourseDetailController(IEventService eventService, ISitePageFactory pageFactory)
{
_pageFactory = pageFactory;
_eventService = eventService;
}
public async Task<ActionResult> CourseDetail()
{
var homepage = _pageFactory.GetCurrentHomepage();
var model = Mapper.Map<CourseDetailVM>(CurrentContent);
model.Email = homepage.ContactEmail;
model.PhoneNumber = homepage.HeaderPhoneNumber;
model.InnerPageHeader.ShowHeading = true;
model.InnerPageHeader.Title = model.PageTitle;
if (model.Categories.Count == 1)
{
var categoryTagId = model.Categories.First().Id;
var contentTypeAlias = DocumentTypeHelper.GetDocumentTypeAlias<CourseListingPageDT>();
var courseCategoryPage = Umbraco.TypedContentAtXPath($"//{contentTypeAlias}")
.FirstOrDefault(x => x.GetPropertyValue<int>(Constants.DocumentTypes.CourseListingPage.Category) == categoryTagId);
if (courseCategoryPage != null)
{
model.InnerPageHeader.BackLink = Mapper.Map<LinkItem>(courseCategoryPage.Id);
}
}
try
{
model.Events = await _eventService.GetEventsForCourse(CurrentContent.AdministrateId);
}
catch (Exception ex)
{
model.Events = new StaticPagedList<Event>(Enumerable.Empty<Event>(), 1, 1, 0);
Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
}
if (CurrentContent.Graphic != 0)
{
model.InnerPageHeader.Graphic = Mapper.Map<CtaItem>(CurrentContent.Graphic);
}
return View(model);
}
}
I've tried every suggestion I can google to add the mapping in the controlling but can't get my head around this simple function of pulling the value from a SQL database into the razor view.
Could anyone help me out?

RavenDB issue storing object that inherits List<T>

I have a class that inherits from List, this class has some additional properties on it. When I store the parent document in RavenDB, the list items get stored but the additional properties do not.
The failing test below probably explains my issue better:
[TestFixture]
public class RDBIssueTests
{
private DocumentStore _documentStore;
[TestFixtureSetUp]
public void TestFixtureSetUp()
{
_documentStore = new EmbeddableDocumentStore
{
RunInMemory = true,
UseEmbeddedHttpServer = true,
DataDirectory = "Data",
};
_documentStore.Initialize();
}
[Test]
public void StoreSimpleDataTest()
{
string id = "people/1";
string laptopName = "MacPro";
string personName = "Joe Bloggs";
string attrOne = "Screen";
string attrTwo = "Keyboard";
var person = new Person()
{
Id = id,
Name = personName,
Laptop = new Possession<string>()
};
person.Laptop.Name = laptopName;
person.Laptop.Add(attrOne);
person.Laptop.Add(attrTwo);
using (var session = _documentStore.OpenSession())
{
session.Store(person);
session.SaveChanges();
}
using (var session = _documentStore.OpenSession())
{
var loadedPerson = session.Load<Person>(id);
Assert.AreEqual(personName, loadedPerson.Name);
Assert.AreEqual(2, loadedPerson.Laptop.Count); // 2 items in the list
Assert.IsTrue(loadedPerson.Laptop.Contains(attrOne));
Assert.IsTrue(loadedPerson.Laptop.Contains(attrTwo));
Assert.AreEqual(laptopName, loadedPerson.Laptop.Name); // fails here - Person.Laptop.Name is not persisted in RBD
}
}
}
public class Person
{
public string Id { get; set; }
public string Name { get; set; }
public Possession<string> Laptop { get; set; }
}
public class Possession<TValueType> : PossessionAttribute<TValueType>
{
public string Name { get; set; } // RDB doesn't persist this value
}
public class PossessionAttribute<TValueType> : List<TValueType>
{
}
As you can see from the test, the string property 'Name' on the Possession class does not get saved.
Is there something I need to do to get this property to persist?
Many thanks!
JSON has no way of representing an object that is both a list and has properties.
That is why you cannot do that. You can have an object that contains a list property, which is a more natural way of going about it.

Problem retrieving results from an index in an embedded RavenDB

I have an index that works great when I query it using the .Net client API with a server based RavenDb.
However, if I change the RavenDb to an embedded type then I cannot query the index directly unless I first query the document that the index uses.
For instance if I have the following document objects which reside as separate collections in the RavenDb:
private class TestParentDocument
{
public string Id { get { return GetType().Name + "/" + AggregateRootId; } }
public Guid AggregateRootId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
private class TestChildProductFlagDocument
{
public string TestParentDocumentId { get; set; }
public short ProductFlagTypeId { get; set; }
}
Then I have the following object which represents the output document that the index maps to:
private class TestJoinIndexOutput
{
public string TestParentDocumentId { get; set; }
public string Name { get; set; }
public short ProductFlagTypeId { get; set; }
}
Here is the index definition:
private class TestJoinIndex : AbstractIndexCreationTask<TestChildProductFlagDocument, TestJoinIndexOutput>
{
public TestJoinIndex()
{
Map = docs => from doc in docs
select new
{
TestParentDocumentId = doc.TestParentDocumentId,
ProductFlagTypeId = doc.ProductFlagTypeId
};
TransformResults = (database, results) =>
from result in results
let parentDoc = database.Load<TestParentDocument>(result.TestParentDocumentId)
select new
{
TestParentDocumentId = result.TestParentDocumentId,
ProductFlagTypeId = result.ProductFlagTypeId,
Name = parentDoc.Name
};
}
My code to call the index looks like so:
var theJoinIndexes = ravenSession.Query<TestJoinIndexOutput, TestJoinIndex>().ToList();
This returns almost immediately and fails unless I do the following:
var theParentDocuments = ravenSession.Query<TestParentDocument>().ToList();
var theJoinIndexes = ravenSession.Query<TestJoinIndexOutput, TestJoinIndex>().ToList();
My Ravendb embedded definition looks like so:
docStore = new EmbeddableDocumentStore
{
UseEmbeddedHttpServer = false,
RunInMemory = true
};
docStore.Configuration.Port = 7777;
docStore.Initialize();
IndexCreation.CreateIndexes(typeof(TestJoinIndex).Assembly, docstore);
You aren't waiting for indexing to complete, call WaitForNonStaleResultsAsOfNow