How To show blank datepicker when DB value is null - c#

I've got a SQL DB column for DateTime Birthday on a customer object. The database allows that field to be null, but occasionally our users populate the data (from another system) with 1/1/1900.
I'd like to have my DatePicker field show nothing when the date in the DB is either null or DateTime.Parse("1900-01-01 00:00:00.000"). (It doesn't have to be fully blank, but can have the DatePicker field's standard default of " / / ".
I've been trying this:
dtBirthday.Value = customer.Birthday.HasValue ? customer.CustomerOptions.Birthday.Value : DateTime.Parse("1900-01-01 00:00:00.000");
That works fairly well for the null birthdays, but doesn't allow for the date in customer.Birthday actually being DateTime.Parse("1900-01-01 00:00:00.000").
Update
I did, in fact, google this, and attempted to use
var nullDate = DateTime.Parse("1900-01-01 00:00:00.000");
if (customer.Birthday.Value == nullDate)
{
dtBirthday.Format = eDateTimePickerFormat.Custom;
dtBirthday.CustomFormat = " ";
dtBirthday.Value = DateTime.FromOADate(0);
dtBirthday.Enabled = true;
}
else
{
dtBirthday.Format = eDateTimePickerFormat.Custom;
dtBirthday.CustomFormat = "M/d/yyyy";
dtBirthday.Value = customer.Birthday.Value;
dtBirthday.Enabled = true;
}
//dtBirthday.Value = customer.Birthday.HasValue ? customer.Birthday.Value : DateTime.Parse("1900-01-01 00:00:00.000");
if (customer.Anniversary.Value == nullDate)
{
dtAnniv.Format = eDateTimePickerFormat.Custom;
dtAnniv.CustomFormat = " ";
dtAnniv.Value = DateTime.FromOADate(0);
dtAnniv.Enabled = true;
}
else
{
dtAnniv.Format = eDateTimePickerFormat.Custom;
dtAnniv.CustomFormat = "MM/dd/yyyy";
dtAnniv.Value = customer.Anniversary.Value;
dtAnniv.Enabled = true;
}
//dtAnniv.Value = customer.Anniversary.HasValue ? customer.Anniversary.Value : DateTime.Parse("1900-01-01 00:00:00.000");
It does just about exactly what I want, except that the empty fields are completely disabled, even though I've specifically set them to enabled=true.

If I'm reading your question correctly, I think you want the text field to be empty when the birthday is actually null. Why not just populate it with an empty string:
txtBirthday.Value =
customer.Birthday.HasValue ?
customer.CustomerOptions.Birthday.Value.ToString() :
string.Empty;

After attempting several dozen different methods, none of which really did what I want, it occurred to me that I could just not set the value.
var nullDate = DateTime.Parse("1900-01-01 00:00:00.000");
if (customer.CustomerOptions.Birthday.HasValue && customer.CustomerOptions.Birthday.Value != nullDate)
{
dtBirthday.Value = customer.CustomerOptions.Birthday.Value;
}
if (customer.CustomerOptions.Anniversary.HasValue && customer.CustomerOptions.Anniversary.Value != nullDate)
{
dtAnniv.Value = customer.CustomerOptions.Anniversary.Value;
}

Related

C#: What is this statement doing? dynObj.#switch == 1 ? true : false

I recently took over some code and came a across a statement that I wasn't sure what it was doing so I decided to post it.
currCarbon.CleanGeneration = (dynObj.#switch == 1 ? true : false);
Since 'dynObj' is a dynamic object holding a json value, is it checking if 'dynObj' contains a 'Switch' key / value?
Thanks for you help!
dynamic dynObj = GetValues();
if (dynObj != null) //json string from API
{
// Read the first record's carbon index
var prevCarbon = _dbContext.WatttimeApilog.OrderByDescending(c => c.CreatedDate).FirstOrDefault();
if (prevCarbon == null) //NO previous carbon value from database
{
//Plug in default values
currCarbon.Percentage = defaultPercent;
currCarbon.CleanGeneration = false;
currCarbon.Rating = defaultRating;
currCarbon.ValidUntil = DateTime.UtcNow;
insertFlag = true;
}
else
{
currCarbon.Percentage = dynObj.percent;
currCarbon.CleanGeneration = (dynObj.#switch == 1 ? true : false);
currCarbon.Rating = Convert.ToByte(dynObj.rating);
currCarbon.ValidUntil = dynObj.validUntil;
}
It's setting CleanGeneration to true or false based on whether or not #switch is equal to one via a ternary operator.
EDIT: The code isn't the most clean and can be shortened to just currCarbon.CleanGeneration = dynObj.#switch == 1;
Linked is docs on the ternary operator:
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/conditional-operator

C# NetSuite WebServices: Get value from custom field in saved search (ItemSearchAdvanced)

I'm using C# MVC to connect to NetSuite using their WebServices API. I have some current code that calls a saved search of inventory items. Here is the current code that is working perfectly:
ItemSearchAdvanced searchItems = new ItemSearchAdvanced();
searchItems.savedSearchId = "128";
SearchResult result = netSuiteSvc.search(searchItems);
int totalRecords = 0;
int processedRecords = 0;
UpdateNetsuitePriceListModel returnObj = new UpdateNetsuitePriceListModel();
returnObj.NewPriceList = new List<NetSuitePriceListRecord>();
if (result.status.isSuccess)
{
SearchRow[] searchRows = result.searchRowList;
if (searchRows != null && searchRows.Length >= 1)
{
for (int i = 0; i < searchRows.Length - 1; i++)
{
ItemSearchRow itemRow = (ItemSearchRow)searchRows[i];
if (itemRow.basic.itemId != null && itemRow.basic.mpn != null && itemRow.basic.basePrice != null && itemRow.basic.salesDescription != null)
{
returnObj.NewPriceList.Add(new NetSuitePriceListRecord()
{
ItemId = itemRow.basic.itemId[0].searchValue,
ManufacturerPartNumber = itemRow.basic.mpn[0].searchValue,
ContractPrice = Convert.ToDecimal(itemRow.basic.basePrice[0].searchValue),
Cost = CalculateProductCostForIngram(Convert.ToDecimal(itemRow.basic.basePrice[0].searchValue)),
Description = itemRow.basic.salesDescription[0].searchValue
});
processedRecords++;
}
totalRecords++;
}
}
else
{
throw new Exception("NetSuite Part List Blank");
}
}
else
{
throw new Exception("NetSuite Part List Search Failure");
}
Now I have need to pull the itemId from a custom added field rather than the default itemId field.
Obviously since this is a custom field it isn't a property of ItemSearchRowBasic. It looks like instead of the property I can choose "customFieldList" which is an array of "SearchColumnCustomField". If I choose an index for the array I can see that SearchColumnCustomField contains:
customLabel
internalId
scriptId
I imagine I should be able to get the internalId of the SearchColumnCustomField and somehow use that to get the search value for that custom column but I've had some trouble finding any examples that fit so far.
This custom field is a free form text field added to all inventory items.
Try setting scriptId with the ID of the field ("custitem_xyz"). That should work.
Before 2013 one would use internalId, but since then it changed to scriptId.
You would need to loop over the CustomRecord items in the customFieldList. I then usually check for a specific type so I can cast to the correct object, but with some reflection you could probably avoid that.
foreach (Record r in mySearchResponse.recordList){
foreach (CustomFieldRef cr in ((CustomRecord)r).customFieldList){
if (cr.GetType().Name == "SelectCustomFieldRef"){
if (((SelectCustomFieldRef)cr).scriptId == "my_custom_field"){
internalID = ((CustomRecord)r).internalId;
}
}
}
}

Streamwriter unresponsive to conditionals

I'm trying to test for null values of two particular fields, and if they're null, replace the whitespace with the amount of 0s appropriate for that field. My code below gives no errors, but isn't doing anything and the normal values are being used.
var replace1 = "00";
var replace2 = "0";
var downpay = _Reader[26].ToString();
var preauth = _Reader[28].ToString();
if(downpay == null || downpay == " ") { downpay = replace1; }
if(preauth == null || preauth == " ") { preauth = replace2; }
writer.WriteLine("{0}{1}{2}{3}{5}{6}{7}{15}{16}{17}{18}{19}{20} 0{21}{22}{23}{24}{25}{26}{27}{28}{29}{30}{31}{32}{33}{34}{35}{36}{37} {38}{39}{40}{41}{42}{43}{44}{45}{46}{47}{48}{49} {50}", _Reader[1], _Reader[2], _Reader[3], _Reader[4], _Reader[5], _Reader[6], _Reader[7], _Reader[8], _Reader[9], _Reader[10], _Reader[11], _Reader[12], _Reader[13], _Reader[14], _Reader[15], _Reader[16], _Reader[17], _Reader[18], _Reader[19], _Reader[20], _Reader[21], _Reader[22], _Reader[23], _Reader[24], _Reader[25], downpay, _Reader[27], preauth, _Reader[29], _Reader[30], _Reader[31], _Reader[32], _Reader[33], _Reader[34], _Reader[35], _Reader[36], _Reader[37], _Reader[38], _Reader[39], _Reader[40], _Reader[41], _Reader[42], _Reader[43], _Reader[44], _Reader[45], _Reader[46], _Reader[47], _Reader[48], _Reader[49], _Reader[50], date3);
Update: Fixed the issue using the debugger. The values were \00 and \0, even though when i copy from the field in sql server it's empty.

Logic to check for Null Value in Multiple Textboxes

Hi guys, probably a simple one.
Using C# .Net 4.0 and Visual Studio 2012 Ultimate.
Got the following code:
string part = "";
part = txtIOpart.Text;
txtBatchCV.Text = txtBatchIO.Text;
txtPartCV.Text = part;
txtExternalCV.Text = Sqlrunclass.SplitSpec_External(part, pg);
txtInternalCV.Text = Sqlrunclass.SplitSpec_Internal();
txtABSCV.Text = Sqlrunclass.SplitSpec_cvABS();
txtOilCV.Text = Sqlrunclass.SplitSpec_OilSeal();
txtBarCV.Text = "*" + Sqlrunclass.SplitInfo_ASno(part, pg) + "*";
txtBarNumCV.Text = txtBarCV.Text;
txtLocnCV.Text = Sqlrunclass.SplitInfo_Location();
txtFitsCV.Text = Sqlrunclass.SplitInfo_Desc();
txtHeightCV.Text = Sqlrunclass.SplitSpec_Height();
txtDiameterCV.Text = Sqlrunclass.SplitSpec_Diameter();
txtCirclitCV.Text = Sqlrunclass.SplitSpec_Circlit();
picTypeCV.Image = ftpclass.Download("CVspecType" + Sqlrunclass.SplitSpec_TypeCV() + ".jpg", "ftp.shaftec.com/Images/TypeJpg", "0095845|shafteccom0", "4ccc7365d4");
if (txtBatchCV.Text == null || txtBatchCV.Text == "")
{
txtBatchCV.Text = "ALL";
}
As you can see at the bottom I'm checking the batch, but I need to check all of the data thats being set by a bunch of methods. Each one will have a different txt output if it sees a null or blank txt. Is there anyway to shorten this code?
Try, txtBatchCV.Text For example
//Just for null
txtBatchCV.Text = (txtBatchCV.Text ?? "ALL").ToString();
//for both null and empty string
txtBatchCV.Text = string.IsNullOrEmpty(txtBatchCV.Text) ? "ALL": txtBatchCV.Text;
You could iterate through all the textboxes
foreach (var txt in form.Controls.OfType<TextBox>())
{
switch(txt.Id){
case "txtBatchCV":
// Do whatever you want for txtBatchCV e.g. check string.IsNullOrEmpy(txt.Text)
break;
}
}
I borrowed the above from here:
How do I loop through all textboxes and make them run corresponding actions from action dictionary?
In response to the comment I got from Tim, I've added a bit more code to explain what you could do. My code example was never meant to be a full solution.
TextBox.Text is never null, it will return "" then. If your methods return null you could use the null-coalescing operator:
string nullRepl = "ALL";
txtExternalCV.Text = Sqlrunclass.SplitSpec_External(part, pg) ?? nullRepl;
txtInternalCV.Text = Sqlrunclass.SplitSpec_Internal() ?? nullRepl;
txtABSCV.Text = Sqlrunclass.SplitSpec_cvABS() ?? nullRepl;
txtOilCV.Text = Sqlrunclass.SplitSpec_OilSeal() ?? nullRepl;
txtLocnCV.Text = Sqlrunclass.SplitInfo_Location() ?? nullRepl;
txtFitsCV.Text = Sqlrunclass.SplitInfo_Desc() ?? nullRepl;
txtHeightCV.Text = Sqlrunclass.SplitSpec_Height() ?? nullRepl;
txtDiameterCV.Text = Sqlrunclass.SplitSpec_Diameter() ?? nullRepl;
txtCirclitCV.Text = Sqlrunclass.SplitSpec_Circlit() ?? nullRepl;
For starters you could use string.IsNullOrEmpty(txtBatchCV.Text), it's a convevience method that basically does what you do in the if check.
You can atleast use one of these methods:
string.IsNullOrEmpty(txtBatchCV.Text)
or
string.IsNullOrWhitespace(txtBatchCV.Text)
I would try something like this:
void SetDefaultIfNull(TextBox txt, string defaultVal)
{
if (string.IsNullOrWhitespace(txt.Text))
txt.Text = defaultVal;
}
Then pass each textbox and the default to the method.

Foreach item changes not preserved outside loop

I have seen this question already but it does not explain it so that I understand what is actually going on. I've been developing for years and never come across this before (though my usage of Linq and Parallel is fairly recent).
My code is:
Parallel.ForEach(databaseMetadata.Rows.Cast<DataRow>(), row => {
var fieldName = row.Item("Name", "");
var field = this.Fields.Where(f => f.Name.ToLower() == fieldName.ToLower()).SingleOrDefault();
if(field != null) { field.Validate(this, connection, row); }
});
Within the field.Validate function it sets a property named 'HasBeenValidated' on the field object to true, however, as soon as I come out of this Parallel.ForEach loop, that property is set back to false. Can someone please explain why this is happening and what I can do to ensure that changes within the loops are persisted outside of the loop.
Edited:
Below is a copy of the code in field.Validate:
internal void Validate(EntityAttribute entity, SqlConnection connection, [AllowNull] DataRow metadata) {
this.HasBeenValidated = true;
var isRequired = this.IsRequired;
var maxLength = this.MaxLength;
var isAutoGenerated = this.IsAutoGenerated;
var dataType = this.member.PropertyType;
var dataTypeAsString = "";
if(metadata != null) {
isRequired = metadata.Item("IsRequired", false);
maxLength = metadata.Item("MaxLength", 0);
isAutoGenerated = metadata.Item("IsAutoGenerated", false);
dataTypeAsString = metadata.Item("DataType", "");
if(dataTypeAsString == this.member.PropertyType.ToSqlServerDataType()) { dataTypeAsString = ""; }
} else {
dataTypeAsString = this.member.PropertyType.ToSqlServerDataType();
}
if(metadata == null || isRequired != this.IsRequired || maxLength != this.MaxLength || isAutoGenerated != this.IsAutoGenerated || dataTypeAsString != "") {
var sql = string.Format((metadata == null ? "ALTER TABLE [{0}].[{1}] ADD" : "ALTER TABLE {0} ALTER COLUMN"), entity.Schema, entity.Name) + " " + this.Sql + ";";
if(!connection.ExecuteCommand(sql, 1)) {
throw new InvalidOperationException("Unable to create or alter column '" + this.Name + "' on table '" + entity.Name + "'.");
}
}
}
The HasBeenValidated property is defined on the field object as:
internal bool HasBeenValidated { get; set; }
Thanks in advance.
Apologies if I've wasted anyone's time but I have figured out the cause of this issue. The this.Fields list is an IEnumerable<> of the field type which is queryable. I thought that this would be better than having a greedy list (since this class has a good number of lists on it). The code for generating the Fields list is:
this.Fields = allProperties
.Select(property => new { Property = property, Field = property.GetCustomAttributes(typeof(FieldAttribute), true).SingleOrDefault() as FieldAttribute })
.Where(info => info.Field != null && (info.Field as ListAttribute) == null)
.Select(info => { info.Field.Member = info.Property; return info.Field; });
What I completely failed to realise was that GetCustomAttributes, rather unexpectedly (from my point of view anyway) regenerates a copy of the attribute class each time it is called.
Had this been a simpler class I might have suspected this sooner, but I was also changing properties in the fields class when setting the Member property (i.e. extracting metadata from the info.Property and setting properties within the field class based on the properties of that class) so when I was looking at the field class in the debugger I could see a lot of the properties had been changed (which mislead me to think it was the same instance of the field class and not a copy).
I really apologise if I've wasted anyone's time and effort in this but hopefully by posting my mistake this can help other people in future who might stumble using the GetCustomAttribute in a similar way inside a non-greedy Linq expression.
It looks like you have a synchronization problem with your DataRow objects - are you sure field.Validate doesn't update the property in the database? And that your databaseMetadata isn't just still sitting on the old data?
The arguments connection, row to field.Validate suggest you might be doing something like that...
Try to use a normal for loop and see what happens. Do you have the same problem?
Can you call databaseMetadata.Rows twice and check is it the same instance or different one.
bool isEquals = ReferenceEquals(databaseMetadata.Rows, databaseMetadata.Rows)
If it's doesn't support immutability I expect it to return a copy of rows each time you access Rows property.

Categories

Resources