I am new to C#. I was executing some select queries from database tables using System.Data.SqlClient classes. I got sqlnullvalueexception while executing some select query. On googling I come to know that if the value is null in the database, SqlDataReader.GetString (or it's variants) will throw sqlnullvalueexception.
What is the best coding practice for this?
if (!sqlDataReader.IsDBNull(n)) value = r.GetString(n);
Any better way of coding?
If you don't want to repeat this a lot, just create a helper function, like this:
public static class DataReaderExtensions
{
public static string GetStringOrNull(this IDataReader reader, int ordinal)
{
return reader.IsDBNull(ordinal) ? null : reader.GetString(ordinal);
}
public static string GetStringOrNull(this IDataReader reader, string columnName)
{
return reader.GetStringOrNull(reader.GetOrdinal(columnName));
}
}
Which you can call like this:
value = reader.GetStringOrNull(n);
The code you posted is fine. You could also do something like that :
value = r[n] as string;
If the value in the database is null, r[n] will return DBNull.Value, and the cast to string will return null.
That really is the best way to go about it if you wish to avoid any exceptions. You need to decide whether or not a null field represents an exceptional situation in your code - if it doesn't then use this method. If it does then I would suggest that you either allow the exception to be thrown or catch the exception and wrap it in a more meaniful exception and throw that one.
But the main thing to know is that this is the standard way to retrieve values from a data reader when a null field does not represent an exceptional situation in the application domain.
This worked for me:
value = reader.GetValue(n).ToString();
Related
I am new to C#. I was executing some select queries from database tables using System.Data.SqlClient classes. I got sqlnullvalueexception while executing some select query. On googling I come to know that if the value is null in the database, SqlDataReader.GetString (or it's variants) will throw sqlnullvalueexception.
What is the best coding practice for this?
if (!sqlDataReader.IsDBNull(n)) value = r.GetString(n);
Any better way of coding?
If you don't want to repeat this a lot, just create a helper function, like this:
public static class DataReaderExtensions
{
public static string GetStringOrNull(this IDataReader reader, int ordinal)
{
return reader.IsDBNull(ordinal) ? null : reader.GetString(ordinal);
}
public static string GetStringOrNull(this IDataReader reader, string columnName)
{
return reader.GetStringOrNull(reader.GetOrdinal(columnName));
}
}
Which you can call like this:
value = reader.GetStringOrNull(n);
The code you posted is fine. You could also do something like that :
value = r[n] as string;
If the value in the database is null, r[n] will return DBNull.Value, and the cast to string will return null.
That really is the best way to go about it if you wish to avoid any exceptions. You need to decide whether or not a null field represents an exceptional situation in your code - if it doesn't then use this method. If it does then I would suggest that you either allow the exception to be thrown or catch the exception and wrap it in a more meaniful exception and throw that one.
But the main thing to know is that this is the standard way to retrieve values from a data reader when a null field does not represent an exceptional situation in the application domain.
This worked for me:
value = reader.GetValue(n).ToString();
I am new to C#. I was executing some select queries from database tables using System.Data.SqlClient classes. I got sqlnullvalueexception while executing some select query. On googling I come to know that if the value is null in the database, SqlDataReader.GetString (or it's variants) will throw sqlnullvalueexception.
What is the best coding practice for this?
if (!sqlDataReader.IsDBNull(n)) value = r.GetString(n);
Any better way of coding?
If you don't want to repeat this a lot, just create a helper function, like this:
public static class DataReaderExtensions
{
public static string GetStringOrNull(this IDataReader reader, int ordinal)
{
return reader.IsDBNull(ordinal) ? null : reader.GetString(ordinal);
}
public static string GetStringOrNull(this IDataReader reader, string columnName)
{
return reader.GetStringOrNull(reader.GetOrdinal(columnName));
}
}
Which you can call like this:
value = reader.GetStringOrNull(n);
The code you posted is fine. You could also do something like that :
value = r[n] as string;
If the value in the database is null, r[n] will return DBNull.Value, and the cast to string will return null.
That really is the best way to go about it if you wish to avoid any exceptions. You need to decide whether or not a null field represents an exceptional situation in your code - if it doesn't then use this method. If it does then I would suggest that you either allow the exception to be thrown or catch the exception and wrap it in a more meaniful exception and throw that one.
But the main thing to know is that this is the standard way to retrieve values from a data reader when a null field does not represent an exceptional situation in the application domain.
This worked for me:
value = reader.GetValue(n).ToString();
I would like to create a helper class to do some common task.
For example, I am retrieving some results from Database and then assigning the values to variables. But some of the fields in my records might contain null as well. I would like to check before assigning that the value does not contain any null.
Also there are some variable those are type int, so like to check before parsing to the specific type.
int iValue=int.parse(Helpers.IsNull(dr[colName].toString()));
string strValue=Helpers.IsNull(dr[colName].toString());
How should I create a helper class and what value should I return with IsNull method?
Little confuse..
Thanks
Well what you are trying to acchieve is to avoid the NullReferenceException i guess.
You could achieve this by writing a generic method like this
public static TValue GetValueSafe<TValue,TObject>(TObject obj, Func<TObject,TValue> accessor)
{
if(obj== null)
return default(TValue);
return accessor(obj);
}
Then use it like this:
string strValue = Helpers.GetValueSafe(dr[colName], o => o.toString());
This would either return the value of toString, or if dr[colName] == null returns default(string) which is null.
You could exand this by adding a defaultParameter to define a value on "failure".
However i would'nt recommend using this.
A more radical approach (which would remove the issue) would be to eradicate NULLs from your values altogether.
The simplest way would be through ISNULL() when you query your database:
Where now you do
SELECT MyColumn FROM MyTable
You instead go
SELECT ISNULL(MyColumn, '') AS MyColumn FROM MyTable
Then you can assume no NULLs will get through to your code.
I have a webservice which has a method that returns a List of Payment objects provided with some input parameters. However if the input parameters are not in the correct format, I would like to return an error message which is of type string, not a List of Payment objects. I would like do this using Generic Classes concept in C#. Anyone has any idea about how I can manage to do this ?
Many thanks,
Here is some code:
[WebMethod]
public List<Payment> GetPayments(string firstDate, string lastDate, string entegrationStatus)
{
if (Common.IsDateTime(firstDate) && Common.IsDateTime(firstDate) && Common.IsValidEntegrationStatus(entegrationStatus))
{
return paymentManager.GetPayments(firstDate, lastDate, entegrationStatus);
}
else
{
return "ERROR MESSAGE";
}
}
I'm fairly sure all you need to do is throw an exception in your service method. This will populate the Error property of the async event args that are returned back to the client. The client can check for errors in its 'async completed' event handler using this property and handle it accordingly.
This is probably a better design than just sending back a string as well because it separates a regular return message from an error return message.
It's as simple as:
Edit - Using the code you posted:
[WebMethod]
public List<Payment> GetPayments(string firstDate, string lastDate, string entegrationStatus)
{
if (Common.IsDateTime(firstDate) && Common.IsDateTime(firstDate) && Common.IsValidEntegrationStatus(entegrationStatus))
{
return paymentManager.GetPayments(firstDate, lastDate, entegrationStatus);
}
else
{
throw new ArgumentException("Your error message.");
}
}
If you REALLY want to do it, you can use a Tuple-like class (they introduced Tuples in C# 4.0). If you are using C# 2.0 then you can use KeyValuePair<List<YourObject>, string>. Be aware that I'm NOT suggesting you do it! You should throw an exception, or put the string message as an out parameter.
well you could do something simply like having an ErrorString property on your object, and if your main method fails, set the ErrorString and return null from your method
SomeObject o = new SomeOject();
ILIst<Things> things = o.GetThings();
if(things == null)
Response.Write(o.ErrorString)
A generic isn't really suitable for this use, because you cannot return a generic type based on a runtime condition within a generic method (since the method must be compiled with an exact type to run in the first place).
A common approach is to use an out parameter for your list and your string, and have your method return a bool denoting whether the list was returned. These methods are usually prefixed with Try.... eg
bool TryGetList<T>(out IList<T> lst, out string Error) {
if (!somcondition) {
Error = "err!";
return false;
}
lst = ...
return true;
}
The other technique is simply to use exceptions, but they can be more costly if you are likely to have errors frequently. An ArgumentException for example will let you specify which argument was invalid, and the caller can check the ParamName of the caught exception to decide what he should do afterwards.
First, let me explain the current situation: I'm reading records from a database and putting them in an object for later use; today a question about the database type to C# type conversion (casting?) arose.
Let's see an example:
namespace Test
{
using System;
using System.Data;
using System.Data.SqlClient;
public enum MyEnum
{
FirstValue = 1,
SecondValue = 2
}
public class MyObject
{
private String field_a;
private Byte field_b;
private MyEnum field_c;
public MyObject(Int32 object_id)
{
using (SqlConnection connection = new SqlConnection("connection_string"))
{
connection.Open();
using (SqlCommand command = connection.CreateCommand())
{
command.CommandText = "sql_query";
using (SqlDataReader reader = command.ExecuteReader(CommandBehavior.SingleRow))
{
reader.Read();
this.field_a = reader["field_a"];
this.field_b = reader["field_b"];
this.field_c = reader["field_c"];
}
}
}
}
}
}
This is (obviously) failing because the three this.field_x = reader["field_x"]; calls are throwing the Cannot implicitly convert type 'object' to 'xxx'. An explicit conversion exists (are you missing a cast?). compiler error.
To correct this I currently know of two ways (let's use the field_b example): number one is this.field_b = (Byte) reader["field_b"]; and number two is this.field_b = Convert.ToByte(reader["field_b"]);.
The problem with option number one is that DBNull fields are throwing exceptions as the cast is failing (even with nullable types as String), ant the problem with number two is that it's not preserving null values (the Convert.ToString(DBNull) yields a String.Empty), and I can't use them with enums too.
So, after a couple of lookups on the internet and here at StackOverflow, what I came up with is:
public static class Utilities
{
public static T FromDatabase<T>(Object value) where T: IConvertible
{
if (typeof(T).IsEnum == false)
{
if (value == null || Convert.IsDBNull(value) == true)
{
return default(T);
}
else
{
return (T) Convert.ChangeType(value, typeof(T));
}
}
else
{
if (Enum.IsDefined(typeof(T), value) == false)
{
throw new ArgumentOutOfRangeException();
}
return (T) Enum.ToObject(typeof(T), value);
}
}
}
This way I should handle every case.
Question is: Am I missing something? Am I doing a WOMBAT (Waste Of Money, Brain And Time) as there's a quicker and cleaner way to do it? It's all correct? Profit?
If a field allows nulls, don't use regular primitive types. Use the C# nullable type and the as keyword.
int? field_a = reader["field_a"] as int?;
string field_b = reader["field_a"] as string;
Adding a ? to any non-nullable C# type makes it "nullable". Using the as keyword will attempt to cast an object to the specified type. If the cast fails (like it would if the type is DBNull), then the operator returns null.
Note: Another small benefit of using as is that it is slightly faster than normal casting. Since it can also have some downsides, such as making it harder to track bugs if you try to cast as the wrong type, this shouldn't be considered a reason for always using as over traditional casting. Regular casting is already a fairly cheap operation.
don't you want to use the reader.Get* methods ? The only annoying thing is that they take column numbers so you have to wrap the accessor in a call to GetOrdinal()
using (SqlDataReader reader = command.ExecuteReader(CommandBehavior.SingleRow))
{
reader.Read();
this.field_a = reader.GetString(reader.GetOrdinal("field_a"));
this.field_a = reader.GetDouble(reader.GetOrdinal("field_b"));
//etc
}
This is how I've dealt with it in the past:
public Nullable<T> GetNullableField<T>(this SqlDataReader reader, Int32 ordinal) where T : struct
{
var item = reader[ordinal];
if (item == null)
{
return null;
}
if (item == DBNull.Value)
{
return null;
}
try
{
return (T)item;
}
catch (InvalidCastException ice)
{
throw new InvalidCastException("Data type of Database field does not match the IndexEntry type.", ice);
}
}
Usage:
int? myInt = reader.GetNullableField<int>(reader.GetOrdinal("myIntField"));
You can make a set of extension methods, one pair per data type:
public static int? GetNullableInt32(this IDataRecord dr, string fieldName)
{
return GetNullableInt32(dr, dr.GetOrdinal(fieldName));
}
public static int? GetNullableInt32(this IDataRecord dr, int ordinal)
{
return dr.IsDBNull(ordinal) ? null : (int?)dr.GetInt32(ordinal);
}
This gets a bit tedious to implement, but it's pretty efficient. In System.Data.DataSetExtensions.dll, Microsoft solved the same problem for DataSets with a Field<T> method, which generically handles multiple data types, and can turn DBNull into a Nullable.
As an experiment, I once implemented an equivalent method for DataReaders, but I ended up using Reflector to borrow an internal class from DataSetExtensions (UnboxT) to do the actual type conversions efficiently. I'm not sure about the legality of distributing that borrowed class, so I probably shouldn't share the code, but it's pretty easy to look up for oneself.
The generic hanlding code posted here is cool, but since the question title includes the word 'efficiently' I will post my less generic but (I hope) more efficient answer.
I suggest you use the getXXX methods that others have mentioned. To deal with the column number problem that bebop talks about, I use an enum, like this:
enum ReaderFields { Id, Name, PhoneNumber, ... }
int id = sqlDataReader.getInt32((int)readerFields.Id)
It's a little extra typing, but then you don't need to call GetOrdinal to find the index for each column. And, instead of worrying about column names, you worry about column positions.
To deal with nullable columns, you need to check for DBNull, and perhaps provide a default value:
string phoneNumber;
if (Convert.IsDBNull(sqlDataReader[(int)readerFields.PhoneNumber]) {
phoneNumber = string.Empty;
}
else {
phoneNumber = sqlDataReader.getString((int)readerFields.PhoneNumber);
}