Field Generator for DataRow

I am trying to extend a DataRow object with this general method:

public static T? Get<T>(this DataRow row, string field) where T : struct { if (row.IsNull(field)) return default(T); else return (T)row[field]; } 

It works fine when T int , decimal , double , etc.

But when I try to use a string, I have this error:

"Type" string "must be a type with a null value in order to use it as a parameter of 'T' in general type or method 'System.Nullable'"

How can i fix this?

I know that a row is not a structure, but I do not want to return null if the row field is DBNull.

+4
source share
7 answers

I think this is what you want:

 public static T? GetValue<T>(this DataRow row, string field) where T : struct { if (row.IsNull(field)) return new T?(); else return (T?)row[field]; } public static T GetReference<T>(this DataRow row, string field) where T : class { if (row.IsNull(field)) return default(T); else return (T)row[field]; } 
+6
source

string not a struct , but a class . This is reported by the error message. Just remove the restriction.

You might want to look at DataRowExtensions .

+5
source

Unfortunately, you cannot get the return type Nullable and support reference types using generics unless you specify that you want to return Nullable when making a call

 public static T Get<T>(this DataRow row, string field) { if (row.IsNull(field)) return default(T); else return (T)row[field]; } 

and when you call

 var id = dr.Get<int?>("user_id"); 

I did not test this, just threw it here. Take a picture.

EDIT:

Alternatively, if you really wanted to convert value types to nullables and still be able to support link types, something like this might work

 public static object GetDr<T>(this DataRow row, string field) { // might want to throw some type checking to make // sure row[field] is the same type as T if (typeof(T).IsValueType) { Type nullableType = typeof(Nullable<>).MakeGenericType(typeof(T)); if (row.IsNull(field)) return Activator.CreateInstance(nullableType); else return Activator.CreateInstance(nullableType, new[] { row[field] }); } else { return row[field]; } } 

However for each use

 var id = dr.Get<string>("username") as string; var id = (int?)dr.Get<int>("user_id"); 

This, however, will not be as effective as simply accepting a type with a null value in the parameters of a generic type.

+2
source
 ds.Tables[7].Rows.OfType<DataRow>().ToList().ForEach(f => tempList.Add(new MyEntity { Id = int.Parse(f.ItemArray[0].ToString()), Title = f.ItemArray[1].ToString() })); 
+2
source

As Wes points out, your problem is a constraint on the structure. I would expect the extension method to work without restrictions ...

And now I'm coming back T? Well, I'm not sure, but can you define two variants of the method that bound the struct , and the other a class that returns T ?

+1
source

You have an explicit condition that prevents this from working with a string:

  where T : struct 

System.String is a class, not a structure. If your goal is to handle value types and string, I would make a separate method for the string and leave it separate for the other types.

+1
source

How about something like that? Not exactly the same as your example, but quite useful for reference types, types with null values, and types with null values:

 int v = row.Get<int>("vvv"); // throws if column is null int? w = row.Get<int?>("www"); // set to null if column is null int x = row.Get<int?>("xxx") ?? -1; // set to -1 if column is null string y = row.Get<string>("yyy"); // set to null if column is null string z = row.Get<string>("zzz") ?? "" // set to "" if column is null // ... public static T Get<T>(this DataRow source, string columnName) { if (source == null) throw new ArgumentNullException("source"); if (columnName == null) throw new ArgumentNullException("columnName"); if (columnName.Length < 1) throw new ArgumentException("Name cannot be empty.", "columnName"); if (source.IsNull(columnName)) { T defaultValue = default(T); if (defaultValue == null) return defaultValue; } // throws if the column is null and T is a non-nullable value type return (T)source[columnName]; } 
+1
source

Source: https://habr.com/ru/post/1339061/


All Articles