When designing data tables in the .xsd designer in Visual Studio, there is a property that specifies what to do when the table encounters a null value:
The problem is, if the DataType is System.DateTime, I'm unable to return empty or nothing. It always throws an exception.
As I work around, I can do the following:
If(row.IsDateLastRecallPrintedNull, DateTime.MinValue, row.DateLastRecallPrinted)
But if the value is DbNull.Value, I'd rather just have it return that.
Using IsDateLastRecallPrintedNull isn't a workaround, it's the way it's intended to be used. If you use a nullable date, you can set this to nothing rather than DateTime.MinValue in your code. Alternatively you can change the datatype in the dataset to System.Object, and then you can select '(Nothing)' in the dropdown. Note that you can overtype the NullValue entry in the properties with another value that's appropriate for the data type, although it won't work if you enter DateTime.Minvalue - it'll appear to accept it, but then fail - but you can put in another magic number such as 01/01/1900.
All this is 'by design'.*
Using databinding sidesteps this quagmire to a great extent; if you're reading programmatically from the dataset then IsxxxNull is the way to go.
*I suspect this is too often a Microsoftism for 'we didn't finish it by ship date'
Related
I'm working on a program, and I need to be able to change a setting using a combobox. I'm getting
CS0266 Cannot implicitly convert type 'object' to 'FastColoredTextBoxNS.Language'. An explict conversion exists (are you missing a cast?)
Using the code:
{
fastColoredTextBox1.Language = comboBox1.SelectedItem
}
Does anyone know a simple way to fix this? If any more info is needed, I will gladly edit it in.
You must cast to the desired type, since the SelectedItem property returns the unspecific type Object.
fastColoredTextBox1.Language = DirectCast(comboBox1.SelectedItem, FastColoredTextBoxNS.Language)
Note there is also the CType function. In addition to performing type casts it also performs also type conversions. We do not need a conversion here, if the items in the ComboBox are of the required type. DirectCast just means, okay I know that the item with the runtime type Object is of the required type, just take it as such.
See also:
Casting DataTypes with DirectCast, CType, TryCast
Difference between DirectCast() and CType() in VB.NET
I'm using Authorize.net API and they require card expiration field to be formated as "yyyy-mm". We did that with this simple line of code:
expirationDate = model.Year.ToString("D4") & "-" & model.Month.ToString("D2")
and this absolutelly worked. I still have cards stored in the system that were saved using this method! But today I was testing something completelly unrelated, and wanted to add another card, and bam, this code exploded with this exception:
System.InvalidCastException: 'Conversion from string "D4" to type 'Integer' is not valid.'
Inner exception to that one is:
Input string was not in a correct format.
This just... doesn't make sense to me. Why in the world is it trying to convert format specifier (D4) into an integer? What input string? What in the world changed in two days?
The problem is that your are using a Nullable(Of Integer). This is a different structure that does not support the overloads of the ToString method a normal Integer has.
You can view the overloads of the Nullable structure here.
I suggest you use the GetValueOrDefault() method to get the proper Integer and also apply the value you expect in case the value is Nothing.
If it is impossible that a instance with a Nothing set for the year reaches this method you can simply use the Value property.
I still do not fully understand why you get this strange error message. Maybe you could check out what the actual method that is called is? Pointing at the method should give you that information. It can't be Nullable(Of Integer).ToString
Well, I found a workable solution and something of an answer thanks to #Nitram's comment. The type of Year/Month property has been changed from Integer to Integer?. Obviously, this isn't a very satisfying answer because I still don't understand why the nullable int can't be formatted, and yet the code compiles perfectly. The working solution for me has been using static format method on String as so:
expirationDate = String.Format("{0:D4}-{1:D2}", model.Year, model.Month)
This works fine even with nullable types.
Edited to answer my own question. This appears to be a LINQ/VB bug.
A simple LINQ query returning an anomymous type will sometimes change the field names specified in the query so as to capitalize them. Perhaps passing the result of the query as a parameter to a method call:
someThing.someMethod(From someStuff In stuffList _
Select text = someStuff.Name(), _
value = someStuff.Id
)
where someMethod has signature
Public Sub someMethod(ByVal list As IEnumerable(Of Object))
If you step into the execution of someMethod, and then examine the value of list in quickwatch, you may or see the field names as "text"&"value" or "Text"&"Value".
LINQ queries should not be changing the field names as specified in the query, so the correct behavior is fieldnames "text"&"value". Yet production builds of our application have the incorrect capitalization behavior (which can be determined indirectly), and debug builds have shown it both happening both ways at different times and/or for different developers' machines.
I've looked high & low for some feature of LINQ which controls this behavior, but now am virtually certain it is a bug. (msdn forum thread, MS Connect bug page)
This is likely to only cause a problem if you are using reflection, such as type.getfield() such as in
listItem = list.ElementAt(index)
itemTextField = listItem.GetType().GetField("text")
itemText = CType(itemTextField.GetValue(listItem),String)
If this happens to you, the workaround is to use overload of GetField with bindingflags to make it case-insensitive:
itemTextField = listItem.GetType().GetField("text", BindingFlags.IgnoreCase)
It must be pretty rare to encounter this bug, but maybe the next person will spend less time scratching their head if they find this info here.
=========original post===========
Getting different behavior in my debug build environment than in my coworkers' and our production envirnonment, relating to LINQ and reflection...
While running debug build of legacy code, the following code
Dim objectType As Type = obj.GetType()
Dim field As FieldInfo = objectType.GetField(name)
Dim prop As PropertyInfo = objectType.GetProperty(name)
results in Nothing for field & prop.
The value of obj is passed down from above and is the result of a LINQ query (it is a single element of the list generated by the query):
From bpt In CustomBProcessTypes Select text = bpt.Name(), value = bpt.Id
The value of name is also passed from above and is "Text" (note capitalization).
I can examine obj in the debugger and confirm that the fieldnames of the object created by the LINQ query are 'text' and 'value' (note lack of capitalization) which is what I would expect.
So failure to find the field by the capitalized name makes sense. However, our production builds and my coworkers builds do not have this problem.
Because calls to type.getfield(string) are expressly cas-sensitive, the only thing I can think of at this point is there must be some configuration of LINQ relating to auto-capitalization of column/fieldnames, and my environment is not set up the same as the others.
Using visual studio 2012. I don't know much of anything about LINQ, per se.
Anyone have any idea what could be going on here?
(NOTE: if I can get an opportunity, I'll have a coworker step through the relevant code and see if in their environment the object created by the linq query ends up with capitalized field names)
EDIT: I verified with a coworker in his debug build: his LINQ query creates a list of objects with field names "Text" and "Value", but on in my environment the LINQ query ends up with field names "text" and "value". The code is the same, but there must be something about how LINQ is configured in my environment which fails to auto-capitalize those field names, but which happens on their machines and in our production environment.
I suppose it is possible that some compiler settings are resulting in different capitalization. Normally this would make no difference because VB.NET is a case-insensitive language so obj.Text and obj.text both work just as well. But to use case insensitivity in reflection lookups, you need to specify it by including BindingFlags.IgnoreCase in the second parameter of GetField or GetProperty:
Dim field As FieldInfo = objectType.GetField(name,
BindingFlags.Public Or BindingFlags.Instance Or BindingFlags.IgnoreCase)
I'm confused as to where name is coming from, though. Some other code is getting the field name from reflection on the query? I didn't see where this was explained in your question.
I have answered my own question (insofar as is possible). Boils down to a bug in LINQ/vb.net.
Fully explained at top of original post (edited in). Hope this saves someone time in the future.
I have been asked to find out why an ajax call doest work if date fields are left blank on a web form, finding out was easy, its because the VB function expects an object with a Date type.
I'm going to convert these values to Nullable(Of Date), but I'm reluctant as this is a class that's quite heavily used and I don't want to break anything else.
My thinking however is that everything calling this class must be sending in a correct Date or it would throw an error currently, so I should be ok.
As long as I check for a value using HasValue and get the date out using Value then I shouldn't have any problems, or is there something else I need to consider?
If you change every reference to use the Date's Value property it will be no worse than what you have now. Then you can add the HasValue checks where you need to.
We have several projects in VB.Net, using .Net Framework 4 and Linq to Entities for many of our SQL queries. Moving to EF is a new shift for us (been using it for about 4-6 months) and has the backing of upper management because we can code so much faster. We still use a lot of stored procs, but we even execute those through Linq to Entities as well.
I'm hoping to clear some confusion up and I can't find a direct answer that makes sense. We have some queries where we want records where a specific field has a NULL value. These are simple select queries, no aggregates or left joins, etc. Microsoft recommends the query look something like this MSDN Link:
dim query = from a in MyContext.MyTables
Where a.MyField = Nothing
Select a
I have several projects where I do exactly this and it works great, no warnings in the IDE. Recently a new project was created by another developer and when he did his null check like above, we all get this warning in the IDE:
Warning 1 This expression will always evaluate to Nothing (due to null propagation from the equals operator). To check if the value is null consider using 'Is Nothing'.
Comparing the projects, option explicit and option strict are on for each one. If we ignore the warning, we get the exact record set we are looking for when the app runs. The warning goes away if I change the = sign to IS. But why did this warning appear in one project and not others? It's confusing when even on MSDN there are examples using the equals operator.
Generated column should be a Nullable(Of T)
So you can check if that field has value or not like this:
dim query = from a in MyContext.MyTables
Where Not a.MyField.HasValue
Select a
I believe what you're seeing here is that MyField is a Nullable(Of T) type. Likely a primitive Integer, Single, etc ...
The reason you're seeing this warning is because the compiler promotes the normal equality operator for the primitive type to the Nullable(Of T) version. It essentially executes the following
Dim myField As Integer? = a.MyField
Dim other As Integer? = Nothing
If myField = other Then
...
End If
The issue though is that when Integer? has the value Nothing it won't compare equal to anything. Hence the above Where clause will always return False. The compiler is attempting to warn you about this problematic corner of Nullable(Of T) and push you to a Is Nothing check which will determine if a.MyField has a non-null value.
This blog article has a very detailed explanation of why this warning is being generated and all of the mechanics behind it. The article is written for C# but the basic premise is applicable to VB.Net as well.
http://blogs.msdn.com/b/abhinaba/archive/2005/12/14/503533.aspx
At least in LINQ to objects you can use this instead:
Nullable(Of Integer).Equals(a, b)
This works fine with both, either or none of the two values being Nothing.