How To Handle DBNull When Pulling data from DataAdapter - c#

I've imported a MSSQL dataset into the DataSet Designer of Visual Studio but I'm having trouble with non-nullable types. My database allows for null integers (and i'd like to keep it that way if possible), but integers in .NET cannot be null. I would love to use nullable integers in .NET, but that datatype doesn't seem to be an option allowed in the drop-down list of the DataSet Designer's DataType property.
I'd prefer not to manually have to edit the DataSet.Designer class file every time I make a schema change in order to change the data-type to a nullable integer. I just want my property to return Null/Nothing instead of throwing a StrongTypingException when I reference a property that is DBNull.
I see that there is a NullValue column property in the DataSet Designer, but I am not allowed to select "Return Null" unless my datatype is an Object.
Is there a clean way to handle the DBNULL > Null conversion using settings in the designer or a neat wrapper function? I don't want to have to use the IsColumnNameNull() Functions for every column every single time I call one of these properties. I also don't want to have to cast Objects into their actual types every single time.
Let me know if I'm looking at this problem the wrong way. Any feedback is appreciated. Thanks!

You can use generic extension method .Field<T>("ColumnName") from System.Data.DataSetExtensions assembly.
int? intValue = datarow.Field<int?>("CustomerId"); // c#
Dim intValue As Integer? = datarow.Field(Of Integer?)("CustomerId") ' vb.net
But you can create a class with correct types which represents data of one row instantiate it only once for use.
Or get rid of DataSet, DataTable and DataRow types and use light "POCO" classes with defined types for properties.
By using classes you made your application little bid more scalable for future changes - for example moving from DataSets to some ORM Frameworks, with classes you can change data access without affecting main business logic.

Related

OrderBy on mix of DateTime and DBNull values throws error

I want to order a list of my 'SortObject' class. This class is meant to imitate a DataGrid Row by holding arbitrary data organized in a dictionary (named 'Cells'), where the key is analogous to a DataGrid Column. It is enforced that any given key is associated with only one data type, for example the key "Name" will only have values of the String type.
My code (below) actually works for a majority of the cases I've used:
// public Dictionary<string, object> Cells { get; set; } <-- relevant field from 'SortObject'
List<SortObject> sortObjects = GetSortObjects(); // This is simplified, the data has a few different sources
IOrderedEnumerable<SortObject> orderedList = sortObjects.OrderBy(p => p.Cells["ArbitraryKey"]);
SortObject firstObject = sortedList.First();
// other work with 'orderedList' follows
The problem occurs when I'm trying to OrderBy objects of the DateTime type, and some of those objects are not set and default to 'System.DBNull'. In this case an exception is thrown when calling 'sortedList.First()' or in any of the later references to 'sortedList'. The exception is simple: "Object must be of type DateTime", which seems to be a consequence of OrderBy trying to compare the type DateTime to the type DBNull.
I've tried two solutions that haven't worked so far:
Attempt One: Set DBNull to new DateTime. In theory this should work, but I would need to create not simply DateTime type objects, but objects of any arbitrary type on the fly. (I'd also need to take note of these SortObjects and set their data back to DBNull once I had the order correct; I can't be actually changing data after all).
Attempt Two: Organize just DBNull, then just DateTime, then slap them together. Again this might work in theory, but the "other work" mentioned in the code snippet is extensive, including reordering using ThenBy() an arbitrary number of times on any key(s). Doubling its complexity is not an elegant solution and I consider it a backup.
What is the best way to resolve this?
PS: For OrderBy and DateTime I'm using the Microsoft .NET Framework v4.6.2
Change the OrderBy statement to OrderBy(v => v is DBNull ? null : v)
OrderBy can handle nulls, but not dbNulls.
That code should work for all the data types

Dynamic column datagrid in wpf

I have a case where in the columns of Datagrid are not fixed . i.e it has to be generated depending on some conditions.
How can i store the values in the DB and display the datagrid with them using MVVM pattern.
P.S : I have a main grid and a sub grid and depending on the value he chooses in the main grid i need to form the below grid. My concern also in storing it in the DB, since there can be 5 columns or sometimes 20.
Any similar links or references will also be useful.
This can be totally done in an MVVM compliant way, but isn't necessarily trivial for a beginner, and isn't appropriate for simple applications.
One approach I like to use is to keep a collection of column descriptors serialised in the database1. The column descriptors are simply my own custom DTO data classes and contain properties related to a column, i.e. width, column type, whether it is visible, whether it's visibility can be toggled, it's ordinal, etc. This is all done using simple structs and or primitive .Net types, but specifically doesn't have any UI related data types in it at all2.
This list of ColumnDescriptors can then be serialiased to and from XML, and stored in the database either in an nvarchar or XML column. Especially on SQL Server an XML column is better as you can natively query deep into the XML structures stored in the database column.
As it is a UI layout thing, it is up to the view to query the right set of column descriptors from the database, I then pump that collection through a static GridColumnFactory class which iterates the descriptor objects and creates me the appropriate grid columns and assigns the appropriate values to them. Once the factory returns that collection the view can then add them to the DataGrid's columns collection.
The benefits of this approach:
If I swap out the DataGrid that is used (i.e. swap from one vendor to another, say DevExpress to ComponentOne or native WPF), I can simply change the types of columns returned from the factory class
If I swap anything in the UI then I don't need to touch the column descriptors that are stored.
Serialising to and from XML means that if I do add/remove properties from the descriptors then older stored copies can still be accommodated, they aren't instantly broken the moment I release an update
One of the best features of all is that I can change the stored column layouts with a simple SQL statement, I don't have to also release compiled code
One last thing - using column descriptors makes it trivial to implement a user specified layout, i.e. when you let them drag columns around and then want to save the layout for next time
If I want to get really funky, the column descriptors can be returned from a webservice
1 For a website these could also be stored in a loose XML file which is then read in and kept in cache.
2 For this approach you should always avoid using specialised or vendor specific data types, as they don't necessarily serialise well (if at all), and will become a weak point in the future - these will be the most likely things you have to change, and if these change you break any stored descriptors you've already got.

Creating an enum/class from a Database Table

I have a database table that essentially contains different types of things. I'll use animals as an example. I have a table called AnimalTypes:
AnimalTypes
{
ID:int,
Name:string
}
I then populate it with:
1:Dog,
2:Cat,
3:Fish
I would like to then have some sort of C# object created that functions similar to this enum be entirely read from the database:
enum AnimalTypes
{
Dog = 1,
Cat = 2,
Fish = 3
}
Is there a way to create an enum/class from a database table as described? I basically want to be able to reference things in the AnimalTypes table using intellisense and AnimalTypes.Dog as an example; I don't actually need an enum, just something that kind of functions like one. Is this possible?
Edit: I'm not really that thrilled about generating a DLL as I've seen in other related problems. I feel like this should be possible with reflection.
Lets suppose I don't need intellisense.
You will have to generate an assembly if you want to be able to use the enumeration or class at compilation time. Reflection happens at execution time so that won't give you intellisense.
This is a common problem - there are a set of distinct values in a database table and those values don't change often so they are modeled as an enum in the source code. This allows these somewhat static values to be easily used in a very readable way. The problem is that when the values do change, it would be nice if the enum changed as well.
The problem with trying to keep the enum and database in sync is that an automatic process doesn't change the fact that if you are changing the database it would be very unlikely that you would do so without having to roll new code to leverage the changed value. It is better to model these values as an enum and still store them in the database. Just manually sync them as the need arises.
Try this solution:
"Creating Enums from database lookup tables"
using T4 code generation for lookup tables.
There's always code generation: http://www.mygenerationsoftware.com/ if you don't want to go the reflection route.

Serializing Object - Replacing Values

I've got a collection of around 20,000 objects that need to get persisted to my database. Now, instead of doing 20,000 insert statements, I want to pass all the records in using an XML parameter.
As far as serializing the object and passing it into the procedure goes, I'm all set. However, I'm wondering if anyone has an elegant way to do the following:
In our C# code base; we have some static values that represent a NULL when saved to the database. For example, if an integer equals -1, or a DateTime equals DateTime.MinValue; save NULL. We have our own little custom implementation that handles this for us when saving objects.
Is there any way I can do something similar to this when performing the XML serialization? Right now it's outputting -1 and DateTime.MinValue in the XML. I do have an extension method (IsNull()) that will return true/false if the value being saved is the null default value.
Any suggestions? Tips/Tricks?
The XmlSerializer understands a number of different attributes; one of them is DefaultValueAttribute.
When included, the XmlSerializer will only serialize the value check if the actual value differs from the default, so all you should need is:
[DefaultValue(-1)]
public int SomeProperty
{get;set;}
Also, if you haven't considered it, take a look at the SqlBulkCopy class, which is a highly-performant approach to sending a large number of records to SQL Server.
You can implement IXmlSerializable to control an object's XML serialization. In particular, implement WriteXml to substitute blank or xsi:null values (however you want to handle this) for those properties/fields that contain your null signifier values.

Linq to DataTable without enumerating fields

i´m trying to query a DataTable object without specifying the fields, like this :
var linqdata = from ItemA in ItemData.AsEnumerable()
select ItemA
but the returning type is
System.Data.EnumerableRowCollection<System.Data.DataRow>
and I need the following returning type
System.Data.EnumerableRowCollection<<object,object>>
(like the standard anonymous type)
Any idea?
Thanks
If I understand you correctly, you'd like to get a collection of objects that you don't need to define in your code but that are usable in a strongly typed fashion. Sadly, no you can't.
An anonymous type seems like some kind of variant or dynamic object, but it is in fact a strongly typed class that is defined at compile time. .NET defines the type for you automatically behind the scenes. In order for .net to be able to do this, it has to have some clue from the code with which to infer the type definition. It has to have something like:
from ItemA in ItemData.AsEnumerable()
select ItemA.Item("Name"), ItemA.Item("Email")
so it knows what members to define. There's no way to get around it, the information has to logically be there for the anonymous type to be defined.
Depending on why exactly your are trying to do this, there are some options.
If you want intellisense while still encapsulating your data access, you can return xml instead of a datatable from your encapsulated data access class. (You can convert data tables to xml very easily. You'll want to use the new System.Xml.Linq classes like the XElement. They're great!) Then you can use VS2008's ability to create an xsd schema from xml. Then use/import that schema at the top of your code page, and you have intellisense.
If you have to have an object an with properties for your data, but don't want to define a class/structure for them, you'll love the new dynamic objects coming in C#4.0/VB10. You have object properties based on what the sql returns, but you won't have intellisense. There is also a performance cost to this, but (a) that might not matter for your situation and (b) it actually is not so bad in some situations.
If you're just trying to avoid making a lot of classes, consider defining structs/structures on the same code file, beneath your class definition. When you add more columns to your result set, it's easy to adjust a struct with more public fields.
In short you can have any two of the following three: (a) dynamic, (b) strontly-typed objects, (3) intellisense. But not all three.
There is one way to accomplish what you want, but it required knowledge of dynamic linq. You would build the query during run-time and then use it. I am no expert and have never really played around with it, but here is a link to Scott Guthrie's blog about it - Dynamic Linq. Hope that helps.
Wade

Categories

Resources