I have an issue converting values from a column called OpeningDate in C#
When i tried to convert where the value is null, the output "return error string parse"
I tried the following code in C#
// Get items from sharepoint list
try
{
context.Load(items, its => its.Include(
i => i.Id,
i => i["SOQAssignmentCode"],
i => i["OpeningDate"]
));
}
catch (Exception d)
{
ComponentMetaData.FireError(0, "", "Error on Load context SP Source." + d.Message, "", 0, out vbool);
}
try
{
context.ExecuteQuery();
}
catch (Exception d)
{
ComponentMetaData.FireError(0, "", "Error on ExecuteQuery SP Source." + d.Message, "", 0, out vbool);
}
Conversion process which seems to be failed
try
{
//Récupérations des données
string ac = string.Empty;
string ast = string.Empty;
string dateValue = null;
string emptyString = "01/01/1900 00:00:00";
string dateValue4 = null;
foreach (ListItem listItem in items)
{
dateValue = listItem["OpeningDate"]?.ToString() ?? emptyString;
dateValue4 = listItem["OpeningDate"]?.ToString() ?? null;
var dateValue2 = DateTime.ParseExact(dateValue4,"yyyy/mm/dd", null);
if (listItem["SOQAssignmentCode"] != null)
{
foreach (ListItem item_not_to_take in listItems_not_to_take)
{
if (listItem["SOQAssignmentCode"].ToString() != item_not_to_take["SOQAssignmentCode"].ToString())
// MessageBox.Show(item_not_to_take["SOQAssignmentCode"].ToString());
ac = listItem["SOQAssignmentCode"].ToString();
Output0Buffer.AddRow();
Output0Buffer.SOQAssignmentCode = ac;
Output0Buffer.SOQOpeningDate = dateValue2;
Output0Buffer.SPID = listItem.Id;
Would it be an easier method to get the string into date values ?
How come the conversion seems to fail with empty/ null values ?
The code is convertint the dates to strings at :
dateValue = listItem["OpeningDate"]?.ToString() ?? emptyString;
dateValue4 = listItem["OpeningDate"]?.ToString() ?? null;
The real solution is to not convert to strings in the first place but cast its value to the correct type, eg :
var openingDate = (DateTime?) listItem["OpeningDate"];
The same applies to other fields and types. Instead of calling ToString() on text fields, just cast the value to the correct type.
The variables themselves should be declared inside the loop, not outside. Otherwise it's very easy to end up using a value from a previous iteration before it receives its new value.
In the question's code for example, ac retains the previous iteration's value. The inner loop ends up assigning to the same output buffer multiple times, once for each item in listItems_not_to_take
Finally, a SharePoint list isn't a database table. Iterating over it and accessing values is expensive. Instead of trying to check every item in listItems_not_to_take it's better to extract the codes that aren't allowed in eg a Dictionary or HashSet and check with `Contains:
This snippet doesn't suffer from variable score creep :
var excluded=listItems_not_to_take.Select(item=>(string)item["SOQAssignmentCode"])
.ToHashSet();
foreach (ListItem listItem in items)
{
var openingDate=(DateTime?)listItem["OpeningDate"];
var code = (string)listItem["SOQAssignmentCode"];
if (code!=null && !excluded.Contains(code))
{
Output0Buffer.AddRow();
Output0Buffer.SOQAssignmentCode = code;
Output0Buffer.SOQOpeningDate = openingDate;
Output0Buffer.SPID = listItem.Id;
}
}
Require to change following value in the code
var dateValue4 = (DateTime?)listItem["OpeningDate"] ?? new DateTime(1900,1,1);
Related
I have the following error bellow,
str = TempData["ReportName"].ToString();
System.NullReferenceException: 'Object reference not set to an instance of an object.'
System.Web.Mvc.TempDataDictionary.this[string].get returned null.
Here is my logic: Controller A Set a value of tempData and declare it => navigate to another controller B => TempData["ReportName"] = Value => work fine
Multiples controllers: z, y => I don't want to set the value or declare my TempData then I get an error.
Maybe I'm having an error with my syntax...
report = SetDefaultsForReportObject(report, previewFlag);
var model = new ReportResult()
{
ReportId = Guid.NewGuid().ToString("N"),
Report = report,
};
if ((TempData["ReportName"]?? "") != null)
{
string strPreview = "ProcessJournalPrintPreview";
string str;
str = TempData["ReportName"].ToString();
if (string.Equals(str, strPreview))
{
report.Watermark.Text = "Test";
ViewBag.IsDevExpressReporting = true;
}
else
{
report.Watermark.Text = null;
ViewBag.IsDevExpressReporting = true;
}
}
ViewBag.IsDevExpressReporting = true;
ViewBag.ReportId = model.ReportId;
If the value may or may not exist then you just need to check if it's null. Verbosely that may look like this:
string str = null;
object report = TempData["ReportName"];
if (report != null)
str = report.ToString();
If you're using a more recent version of C#, you might simplify it to:
string str = TempData["ReportName"]?.ToString();
Just keep in mind that in your logic str may also be null, so don't assume it has a value set. Or set a default value:
string str = TempData["ReportName"]?.ToString() ?? "";
I have a dataset in a .csv file in a local folder, below is a sample row of the data, it has 13 attributes to each item.
I am parsing this data in C#, my code has been working for 2 years and I cannot remember
The code reading the .csv file is, this section is parsing the data into compiledList.
static string loadFile(string fileLocation)
{
string text = "";
try
{
text = File.ReadAllText(fileLocation);
}
catch (Exception e)
{
Console.WriteLine("An error has occured...");
Console.WriteLine(e.Message);
}
return text;
}
static ConcurrentBag<Item> interpretFile(string text, ConcurrentBag<Item> compiledList)
{
String[] substrings = text.Split('\n');
int settlementPeriod = -1; int totalSP = -1;
foreach (string line in substrings)
{
String[] items = line.Split(',');
if (items[0] == "HDR")
{
settlementPeriod = int.Parse(items[3]);
if (settlementPeriod > 48)
settlementPeriod -= 48;
if (settlementPeriod < 0)
settlementPeriod += 48;
totalSP = getTotalSettlementPeriod(DateTime.ParseExact(items[2], "yyyyMMdd", null), settlementPeriod);
}
if (items[0] == "BOALF")
{
//Item Bid = new Item(items);
Item Bid = new Item
{
recordType = items[0],
unitID = items[1],
acceptID = float.Parse(items[2]),
acceptTime = DateTime.ParseExact(items[3], "yyyyMMddHHmmss", null),
deemedFlag = ToBoolean(items[4]),
soFlag = ToBoolean(items[5]),
storFlag = ToBoolean(items[6]),
fromTime = DateTime.ParseExact(items[7], "yyyyMMddHHmmss", null),
fromLevel = float.Parse(items[8]),
toTime = DateTime.ParseExact(items[9], "yyyyMMddHHmmss", null),
toLevel = float.Parse(items[10]),
settlementPeriod = settlementPeriod,
totalSP = totalSP
};
compiledList.Add(Bid);
Sample item from the .csv is:
When I open the data set in Notebad below is what i see:
Note that items[0] is the first colum from the about sample data set. there the data which I am now having issues with is column 4 which is '2.02E+13' shown above.
What that actually is '20191211202600' which is the 'yyyymmddhhmmss' in number format. I do not know what has changed such that the below is giving me an error.
acceptTime = DateTime.ParseExact(items[3], "yyyyMMddHHmmss", null)
`
The error that I am getting is:
System.FormatException: 'String was not recognized as a valid
DateTime.'
I would appreciate your assistance and let me know if further clarification is required.
Thanks
I don't think the problem is with your C# code, the columns which contain date format yyyymmddhhmmss should be of type string, where they are now treated as a number. This problem arises from the program you are saving the CSV file (for example excel or google spreadsheets) you need to change the column data type to string (as it is now automatically detected as a number).
The following works in .NET fiddle (https://dotnetfiddle.net/), can you verify the string that is being used in the call to DateTime.ParseExact? Perhaps the string is not equal to what you would expect at runtime.
using System;
public class Program
{
public static void Main()
{
Console.WriteLine(DateTime.ParseExact("20191211202600", "yyyyMMddHHmmss", null));
}
}
Output is:
12/11/2019 8:26:00 PM
I am trying to convert a list of 1000s dynamic (that I get from CsvHelper reading csv file) into static type but its taking forever.
Here's code:
dynamic object
MyObj {
id =1, prop1=1,prop2=2,prop3=3...
}
result
PObj1 { oid = 1 , name = "Property 1", value = "1" }
PObj2 { oid = 1 , name = "Property 2", value = "2" }
PObj3 { oid = 1 , name = "Property 3", value = "3" }
Code to convert
var imp = rows.SelectMany(x => map.Keys.ToList().Select(k => new PObj
{
OID = (((IDictionary<string, object>)x)["oid"] ?? "").ToString(),
Name = k,
Value = ToDate((((IDictionary<string, object>)x)[map[k]] ?? "").ToString())
}).ToList()).ToList();
map contains list of properties about 40-50
map<string,string>{
{"Property 1","prop1"},
{"Property 1","prop2"},
{"Property 1","prop3"}
...
}
ToDate function
private DateTime? ToDate(string strDate)
{
strDate = strDate.Split(' ')[0];
strDate = strDate.Replace('-', '/').Replace('.', '/');
DateTime? dt = null;
try
{
dt = DateTime.ParseExact(strDate, dateFormats, CultureInfo.InvariantCulture, DateTimeStyles.None);
} catch { }
return dt;
}
map can contain any number of peroperties hence expandoObject will have dynamic number of properties.
Is there any way I can improve the performance?
The reason I need to do this conversion is because I need to than send this as table to a stored procedure therefore converting expandoObject straight into table creates issue if number properties in object changes as this mean number of column will also change in table.
I am open to other solutions as well if works in above situation.
seems like it was my pc (running windows on mac). Same code now works fine
rows.ToList().ForEach(x => imps.AddRange(map.Keys.Select(k => new ImportMilestone
{
JVSiteID = (((IDictionary<string, object>)x)[siteid] ?? "").ToString(),
Milestone = k,
MilestoneValue = ToDate((((IDictionary<string, object>)x)[map[k]] ?? "").ToString())
}).ToList()));
I have the following function that searches a database for entries where a column called "description" have the same value. Right now it just returns the first value it finds or a default value is there isn't one.
public static NewCode GetAltCode(int altCodeVer, string descrip)
{
var sql = #"select Code, Description, VersionID from Code.CodeLookup where versionid=#vers and description=#description";
return ObjectFactory.GetInstance<IDatabaseFactory>().Query<NewCode>(sql, new { vers = altCodeVer, description = descrip, }).FirstOrDefault();
}
I have this if statement to check and make sure the result isn't null, and if it is, to say that the "code isn't found"
[Authorize(parentAction: "Edit")]
public ActionResult Lookup(string Code, int? VersionId = null)
{
var Info = VisitViews.GetDescriptionByVersionId(Code, VersionId.HasValue ? VersionId.Value : 9);
var description = string.Empty;
// CHECK FOR NULL
if (Info != null)
{
description = Info.Description;
if (VersionId == 9)
{
var altInfo = VisitViews.GetAltCode(10, description);
}
if (VersionId == 10)
{
var altInfo = VisitViews.GetAltCode(9, description);
}
}
else
description = "CODE NOT FOUND";
return Json(new { Description = description });
}
My question is, instead of doing FirstOrDefault, is there a way to store the results in an array (or even to store them in a list and call ToArray on the list)? I'm trying to get all of the codes received during the sql search instead of just one so that another function I am working on can traverse the array and place the items where they need to be in a UI.
For future reference of this post, here is the answer:
Change the return type to NewCode[] and replace .FirstOrDefault() with .ToArray()
public static NewCode[] GetAltCode(int altCodeVer, string descrip)
{
var sql = #"select Code, Description, VersionID from Code.CodeLookup where versionid=#vers and description=#description";
return ObjectFactory.GetInstance<IDatabaseFactory>().Query<NewCode>(sql, new { vers = altCodeVer, description = descrip, }).ToArray();
}
I have the following code block with in one of my controllers, this code returns two date strings formatted a certain way based on culture for my View to consume.
string dateStringForSystem = "";
string dateStringForActiveMetrics = "";
string cultureConfigKey = System.Configuration.ConfigurationManager.AppSettings["InstanceCulture"];
DateTime? lastEntryDateForSystem = null;
DateTime? lastEntryDateForActiveMetrics = null;
DataSet dSet = DataHelper.Measurements_GetLastMeasurement(userSession.UserIDNative);
foreach (DataRow dr in dSet.Tables[0].Rows)
{
lastEntryDateForSystem = (DateTime?)dr["LastMeasurementWhen"];
lastEntryDateForActiveMetrics = (DateTime?)dr["LastMeasurementForActiveGoalsWhen"];
}
// Format viewdata dates based on culture and convert it to string
if (cultureConfigKey == "en" )
{
ViewData["DateStringForSystem"] = dateStringForSystem = String.Format("{0:MM/dd/yy}", lastEntryDateForSystem);
ViewData["DateStringForActiveMetrics"] = dateStringForActiveMetrics = String.Format("{0:MM/dd/yy}", lastEntryDateForActiveMetrics);
}
else
{
ViewData["DateStringForSystem"] = dateStringForSystem = String.Format("{0:dd/MM/yy}", lastEntryDateForSystem);
ViewData["DateStringForActiveMetrics"] = dateStringForActiveMetrics = String.Format("{0:dd/MM/yy}", lastEntryDateForActiveMetrics);
}
With in the View code I store and use the view data as such. But if the strings return null I'm getting an error. Is null not returned as a string even when I convert the dateTime to a string?
var dateStringForSystem = ViewData["DateStringForSystem"];
var dateStringForActiveMetrics = ViewData["DateStringForActiveMetrics"];
#if (dateStringForSystem == "")
{
// some html
}
else if (dateStringForActiveMetrics != "")
{
<span>#dateStringForActiveMetrics</span>
}
Still pretty new to C#, so any recommendations on cleaning this code up is also greatly appreciated :) Thanks!