DBNull के लिए जाँच करने के लिए और फिर एक चर को असाइन करने के लिए सबसे कुशल तरीका?


151

यह सवाल कभी-कभार सामने आता है, लेकिन मैंने कोई संतोषजनक जवाब नहीं देखा है।

एक विशिष्ट पैटर्न है (पंक्ति एक DataRow है ):

 if (row["value"] != DBNull.Value)
 {
      someObject.Member = row["value"];
 }

मेरा पहला सवाल यह है कि कौन अधिक कुशल है (मैंने शर्त लगा दी है):

  row["value"] == DBNull.Value; // Or
  row["value"] is DBNull; // Or
  row["value"].GetType() == typeof(DBNull) // Or... any suggestions?

यह इंगित करता है कि .GetType () तेज होना चाहिए, लेकिन शायद कंपाइलर कुछ चालें जानता है जो मैं नहीं करता हूं?

दूसरा सवाल, क्या यह पंक्ति ["मूल्य"] के मूल्य को रोकने के लायक है या क्या संकलक किसी भी तरह से अनुक्रमणिका का अनुकूलन करता है?

उदाहरण के लिए:

  object valueHolder;
  if (DBNull.Value == (valueHolder = row["value"])) {}

टिप्पणियाँ:

  1. पंक्ति ["मान"] मौजूद है।
  2. मुझे कॉलम का कॉलम इंडेक्स पता नहीं है (इसलिए कॉलम नाम लुकअप)।
  3. मैं विशेष रूप से DBNull और फिर असाइनमेंट (समय से पहले अनुकूलन के बारे में नहीं, आदि) की जाँच के बारे में पूछ रहा हूँ।

मैंने कुछ परिदृश्‍यों को चिह्नित किया (सेकंड में समय, 10,000,000 परीक्षण):

row["value"] == DBNull.Value: 00:00:01.5478995
row["value"] is DBNull: 00:00:01.6306578
row["value"].GetType() == typeof(DBNull): 00:00:02.0138757

Object.ReferenceEquals का प्रदर्शन "==" के समान है

सबसे दिलचस्प परिणाम? यदि आप मामले के आधार पर कॉलम का नाम मिसमैच करते हैं (उदाहरण के लिए, "वैल्यू" के बजाय "वैल्यू", तो यह लगभग दस गुना अधिक समय लेता है) (एक स्ट्रिंग के लिए):

row["Value"] == DBNull.Value: 00:00:12.2792374

कहानी की नैतिकता यह प्रतीत होती है कि यदि आप इसके सूचकांक द्वारा एक कॉलम नहीं देख सकते हैं, तो यह सुनिश्चित करें कि आप जिस कॉलम का नाम इंडेक्सर को खिलाते हैं, वह DataColumn के नाम से बिल्कुल मेल खाता है।

मूल्य कैशिंग भी तेजी से लगभग दो बार प्रतीत होता है :

No Caching: 00:00:03.0996622
With Caching: 00:00:01.5659920

तो सबसे कुशल तरीका लगता है:

 object temp;
 string variable;
 if (DBNull.Value != (temp = row["value"]))
 {
      variable = temp.ToString();
 }

1
क्या आप स्पष्ट कर सकते हैं कि क्या पंक्ति एक DataRow या IDataRecord / IDataReader है?
मार्क Gravell

7
अब हमारे पास बेहतर .NET फ्रेमवर्क है और हम DataRowExtensions Methods का उपयोग कर सकते हैं ।
पावेल होडेक

यदि आप मामले के आधार पर कॉलम के नाम को मिसमैच करते हैं (उदाहरण के लिए, "मान" के बजाय "मान", तो यह लगभग दस गुना अधिक समय लेता है (एक स्ट्रिंग के लिए) यह पूरी तरह से कार्यान्वयन पर निर्भर करता है। मुझे याद है यह मामला था (परिवर्तन) MySQL ADO.NET कनेक्टर के साथ कॉलम नाम का बहुत धीमा होना), लेकिन SqlServer या SQLite (याद नहीं) के लिए बिल्कुल भी नहीं। चीजें अब बदल गई हैं। हां, मूल दिशानिर्देश है, जब संदेह में, ordinals पर जाएं।
नवाफल

@PavelHodek ऐसी शर्म जो केवल DataRow के लिए है। IDataRecordएक्सटेंशन पसंद करेंगे ।
नवाफाल

जवाबों:


72

मेरा कुछ छूट रहा है। DBNullवास्तव में क्या DataRow.IsNullविधि करता है के लिए जाँच नहीं है?

मैं निम्नलिखित दो एक्सटेंशन विधियों का उपयोग कर रहा हूं:

public static T? GetValue<T>(this DataRow row, string columnName) where T : struct
{
    if (row.IsNull(columnName))
        return null;

    return row[columnName] as T?;
}

public static string GetText(this DataRow row, string columnName)
{
    if (row.IsNull(columnName))
        return string.Empty;

    return row[columnName] as string ?? string.Empty;
}

उपयोग:

int? id = row.GetValue<int>("Id");
string name = row.GetText("Name");
double? price = row.GetValue<double>("Price");

यदि आप के Nullable<T>लिए रिटर्न मान नहीं चाहते हैं GetValue<T>, तो आप आसानी से बदले में default(T)या कुछ अन्य विकल्प वापस कर सकते हैं ।


एक असंबंधित नोट पर, यहां Stevo3000 के सुझाव के लिए एक VB.NET विकल्प दिया गया है:

oSomeObject.IntMember = If(TryConvert(Of Integer)(oRow("Value")), iDefault)
oSomeObject.StringMember = If(TryCast(oRow("Name"), String), sDefault)

Function TryConvert(Of T As Structure)(ByVal obj As Object) As T?
    If TypeOf obj Is T Then
        Return New T?(DirectCast(obj, T))
    Else
        Return Nothing
    End If
End Function

3
दान इस जोखिम को फिर से ओपी से बचना चाहता है। लिखने से row.IsNull(columnName)आप इसे पहले से ही पढ़ रहे हैं और इसे फिर से पढ़ रहे हैं। यह कहते हुए कि फर्क नहीं पड़ेगा, लेकिन सैद्धांतिक रूप से यह कम कुशल हो सकता है ..
nawfal

2
System.Data.DataSetExtensions.DataRowExtensions.Field<T>(this System.Data.DataRow, string)अनिवार्य रूप से पहली विधि के रूप में एक ही काम नहीं कर रहा है?
डेनिस जी

35

आपको विधि का उपयोग करना चाहिए:

Convert.IsDBNull()

फ्रेमवर्क में अंतर्निहित होने को देखते हुए, मैं यह सबसे कुशल होने की उम्मीद करूंगा।

मैं कुछ लाइनों के साथ सुझाव देना चाहता हूँ:

int? myValue = (Convert.IsDBNull(row["column"]) ? null : (int?) Convert.ToInt32(row["column"]));

और हाँ, संकलक को आपके लिए इसे कैश करना चाहिए।


5
ठीक है, सब विकल्पों उल्लेख ढांचे में निर्माण कर रहे हैं ... दरअसल, Convert.IsDBNull IConvertible से संबंधित अतिरिक्त काम का एक बहुत कुछ ... करता है
मार्क Gravell

1
और फिर से कैश करें - यदि आप सशर्त उदाहरण से मतलब रखते हैं, नहीं - यह वास्तव में नहीं होना चाहिए (और नहीं)। यह दो बार अनुक्रमणिका निष्पादित करेगा।
मार्क Gravell

ओह, और वह कोड संकलित नहीं करता है - लेकिन उनमें से एक में एक (int?) जोड़ें, और आप देखेंगे (IL में) 2: callvirt उदाहरण ऑब्जेक्ट [System.Data] System.Data.DataRow :: get_Item (स्ट्रिंग)
मार्क Gravell

20

संकलक दूर अनुक्रमणिका को अनुकूलित नहीं करेगा (यानी यदि आप पंक्ति ["मान"] का दो बार उपयोग करते हैं), तो हाँ यह करने के लिए थोड़ा तेज़ है:

object value = row["value"];

और फिर दो बार मूल्य का उपयोग करें; का उपयोग कर .GetType () जोखिम मुद्दों अगर यह अशक्त है ...

DBNull.Valueवास्तव में एक सिंगलटन है, इसलिए 4 वें विकल्प को जोड़ने के लिए - आप शायद ReferenceEquals का उपयोग कर सकते हैं - लेकिन वास्तव में, मुझे लगता है कि आप यहां बहुत चिंता कर रहे हैं ... मुझे नहीं लगता कि "", "== के बीच की गति अलग है।" “आदि आपके द्वारा देखी जा रही किसी भी प्रदर्शन समस्या का कारण बनने जा रहा है। अपने पूरे कोड को प्रोफाइल करें और उस चीज़ पर ध्यान केंद्रित करें जो मायने रखती है ... यह ऐसा नहीं होगा।


2
वस्तुतः सभी मामलों में == ReferenceEquals (esp। DBNull) के समतुल्य होने जा रहा है और यह बहुत अधिक पठनीय है। अगर आप चाहते हैं तो @Marc Gravell के ऑप्टिमाइज़ेशन का उपयोग करें, लेकिन मैं उसके साथ हूँ - शायद बहुत मदद करने वाला नहीं है। BTW, संदर्भ समानता हमेशा प्रकार की जाँच को हरा देना चाहिए।
tvanfosson

1
अब पुराना है, लेकिन मैंने हाल ही में कई मामलों को देखा है जहां यह वही था जो प्रोफाइलर ने ठीक करने के लिए कहा था। बड़े डेटा सेटों का मूल्यांकन करने की कल्पना करें, जहां हर सेल को यह जाँच करने की आवश्यकता होती है। अनुकूलन है कि बड़े पुरस्कार प्राप्त कर सकते हैं। लेकिन जवाब का महत्वपूर्ण हिस्सा अभी भी अच्छा है: पहला प्रोफाइल , यह जानने के लिए कि अपना समय बिताने के लिए सबसे अच्छा कहां है।
जोएल कोएहॉर्न

मुझे लगता है कि एल्विस ऑपरेटर का सी # 6 परिचय आपके द्वारा सुझाए गए चेक में अशक्त संदर्भ अपवाद से बचना आसान बनाता है। मान .GetType () == टाइपोफ़ (DBNull)
Eniola

हाँ मैं सहमत हूँ। आम तौर पर जाने के लिए एक बेहतर तरीका है, लेकिन उन लोगों के लिए जो टी का उपयोग करना चाहते हैं। गेट टाइप () जिनके जोखिम आपने इंगित किए थे, तब। इसके चारों ओर एक रास्ता प्रदान करता है।
एनिओला

9

मैं C # में निम्न कोड का उपयोग करूंगा ( VB.NET उतना सरल नहीं है)।

कोड मान प्रदान करता है यदि यह शून्य / DBNull नहीं है, अन्यथा यह डिफ़ॉल्ट को असाइन करता है जिसे LHS मान पर सेट किया जा सकता है जो संकलक को अनदेखा करने की अनुमति देता है।

oSomeObject.IntMemeber = oRow["Value"] as int? ?? iDefault;
oSomeObject.StringMember = oRow["Name"] as string ?? sDefault;

1
VB.NET संस्करण है सरल रूप में: oSomeObject.IntMember = If(TryCast(oRow("Value), Integer?), iDefault)
दान ताओ

1
@ दान ताओ - मुझे नहीं लगता कि आपने वह कोड संकलित किया है। मेरा एक पुराना प्रश्न देखें जो बताता है कि आपका कोड काम क्यों नहीं करेगा। stackoverflow.com/questions/746767/…
स्टीववेवेल

और एक बार फिर, अपने कंप्यूटर से दूर एक SO प्रश्न पर टिप्पणी करना (उस पर देव उपकरण के साथ) एक गलती साबित हुई है! तुम सही हो; मुझे यह जानकर आश्चर्य हुआ कि प्रकारों के लिए TryCastC # asऑपरेटर के समान सुविधाजनक कार्यक्षमता प्रदान नहीं करता है Nullable(Of T)। सबसे करीबी तरीका मैं यह सोचकर नकल कर सकता हूं कि यह अपना कार्य लिखना है, जैसा कि मैंने अब अपने उत्तर में सुझाया है।
दान ताओ

आपके पास एक सामान्य विधि में इसे फिर से दर्शाने में कठिन समय होगा, और यदि आप ऐसा करते हैं, तो इसमें शामिल बहुत अधिक कास्टिंग इसे कम दक्षता प्रदान करेगा।
नवाफाल

8

मुझे लगता है कि बहुत कम दृष्टिकोण यहाँ ओपी को सबसे अधिक चिंता का विषय नहीं लगाते हैं (मार्क ग्रेवेल, स्टेवो3000, रिचर्ड सज़ले, नील, डैरेन कोपांड) और अधिकांश अनावश्यक रूप से जटिल हैं। पूरी तरह से अवगत होने के कारण यह बेकार माइक्रो-ऑप्टिमाइज़ेशन है, मैं कहता हूं कि आपको मूल रूप से इन पर काम करना चाहिए:

1) DataReader / DataRow से मूल्य को दो बार न पढ़ें - इसलिए इसे या तो शून्य चेक और कास्ट / कन्वर्सेशन से पहले कैश कर दें या बेहतर तरीके से सीधे record[X]उचित हस्ताक्षर के साथ कस्टम एक्सटेंशन विधि में अपनी वस्तु को पास कर दें।

2) उपरोक्त का पालन करने के लिए, IsDBNullअपने DataReader / DataRow पर निर्मित फ़ंक्शन का उपयोग न करें क्योंकि यह record[X]आंतरिक रूप से कॉल करता है , इसलिए वास्तव में आप इसे दो बार करेंगे।

3) एक सामान्य नियम के रूप में टाइप तुलना हमेशा मूल्य की तुलना में धीमी होगी। बस record[X] == DBNull.Valueबेहतर करो।

4) डायरेक्ट कास्टिंग Convertकॉन्वेंटिंग के लिए कॉलिंग क्लास से तेज होगी , हालांकि मुझे डर है कि बाद वाले कम लड़खड़ाएंगे।

5) अंत में, कॉलम नाम के बजाय इंडेक्स द्वारा रिकॉर्ड एक्सेस करना फिर से तेज होगा।


मुझे लगता है कि सज़ायाल, नील और डैरेन कोपांड के दृष्टिकोण से जाना बेहतर होगा। मुझे विशेष रूप से डैरेन कोपांड की विस्तार पद्धति का तरीका पसंद है, जिसमें IDataRecord(हालांकि मैं इसे और कम करना चाहूंगा IDataReader) और सूचकांक / कॉलम नाम।

इसे कॉल करने के लिए ध्यान रखें:

record.GetColumnValue<int?>("field");

और नहीं

record.GetColumnValue<int>("field");

मामले में आप के बीच अंतर करने की जरूरत है 0और DBNull। उदाहरण के लिए, यदि आपके पास एनम फ़ील्ड में शून्य मान हैं, अन्यथा default(MyEnum)पहले एनम मान वापस किए जाने का जोखिम है। तो बेहतर है कॉल करें record.GetColumnValue<MyEnum?>("Field")

चूँकि आप एक से पढ़ रहे हैं DataRow, मैं दोनों के लिए DataRowऔर कॉमन कोड DRYingIDataReader द्वारा विस्तार विधि बनाऊँगा

public static T Get<T>(this DataRow dr, int index, T defaultValue = default(T))
{
    return dr[index].Get<T>(defaultValue);
}

static T Get<T>(this object obj, T defaultValue) //Private method on object.. just to use internally.
{
    if (obj.IsNull())
        return defaultValue;

    return (T)obj;
}

public static bool IsNull<T>(this T obj) where T : class 
{
    return (object)obj == null || obj == DBNull.Value;
} 

public static T Get<T>(this IDataReader dr, int index, T defaultValue = default(T))
{
    return dr[index].Get<T>(defaultValue);
}

तो अब इसे कॉल करें:

record.Get<int>(1); //if DBNull should be treated as 0
record.Get<int?>(1); //if DBNull should be treated as null
record.Get<int>(1, -1); //if DBNull should be treated as a custom value, say -1

मेरा मानना ​​है कि यह पहली बार में फ्रेमवर्क (बजाय record.GetInt32, record.GetStringआदि तरीकों) में कैसे होना चाहिए था - कोई रन-टाइम अपवाद नहीं है और हमें अशक्त मूल्यों को संभालने की सुविधा देता है।

मेरे अनुभव से मुझे डेटाबेस से पढ़ने के लिए एक सामान्य विधि के साथ कम भाग्य मिला था। मुझे हमेशा विभिन्न प्रकारों को कस्टम करना पड़ता था, इसलिए मुझे लंबे समय में अपनी खुद की GetInt, GetEnumऔर GetGuid, आदि विधियों को लिखना पड़ता था। क्या होगा यदि आप डिफ़ॉल्ट रूप से db से स्ट्रिंग पढ़ते समय सफेद रिक्त स्थान को ट्रिम करना चाहते हैं, या DBNullखाली स्ट्रिंग के रूप में मानते हैं ? या यदि आपका दशमलव सभी अनुगामी शून्य से छोटा होना चाहिए। मुझे उस Guidप्रकार से सबसे अधिक परेशानी हुई जहां विभिन्न कनेक्टर ड्राइवरों ने अलग-अलग व्यवहार किया, वह भी तब जब अंतर्निहित डेटाबेस उन्हें स्ट्रिंग या बाइनरी के रूप में संग्रहीत कर सकते हैं। मेरे पास इस तरह एक अधिभार है:

static T Get<T>(this object obj, T defaultValue, Func<object, T> converter)
{
    if (obj.IsNull())
        return defaultValue;

    return converter  == null ? (T)obj : converter(obj);
}

Stevo3000 के दृष्टिकोण के साथ, मुझे कॉलिंग थोड़ी बदसूरत और थकाऊ लगती है, और इससे एक सामान्य कार्य करना कठिन होगा।


7

परेशानी वाला मामला है जहां वस्तु एक तार हो सकती है। नीचे विस्तार विधि कोड सभी मामलों को संभालता है। यहां बताया गया है कि आप इसका उपयोग कैसे करेंगे:

    static void Main(string[] args)
    {
        object number = DBNull.Value;

        int newNumber = number.SafeDBNull<int>();

        Console.WriteLine(newNumber);
    }



    public static T SafeDBNull<T>(this object value, T defaultValue) 
    {
        if (value == null)
            return default(T);

        if (value is string)
            return (T) Convert.ChangeType(value, typeof(T));

        return (value == DBNull.Value) ? defaultValue : (T)value;
    } 

    public static T SafeDBNull<T>(this object value) 
    { 
        return value.SafeDBNull(default(T)); 
    } 

6

मैं व्यक्तिगत रूप से इस सिंटैक्स का पक्ष लेता हूं, जो स्पष्ट रूप से उजागर किए गए IsDbNull विधि का उपयोग करता है IDataRecord, और डुप्लिकेट स्ट्रिंग लुकअप से बचने के लिए कॉलम इंडेक्स को कैश करता है।

पठनीयता के लिए विस्तारित, यह कुछ इस तरह है:

int columnIndex = row.GetOrdinal("Foo");
string foo; // the variable we're assigning based on the column value.
if (row.IsDBNull(columnIndex)) {
  foo = String.Empty; // or whatever
} else { 
  foo = row.GetString(columnIndex);
}

DAL कोड में कॉम्पैक्टनेस के लिए एक ही लाइन पर फिट होने के लिए फिर से लिखा गया - ध्यान दें कि इस उदाहरण में हम यह बता रहे हैं int bar = -1कि row["Bar"]क्या अशक्त है।

int i; // can be reused for every field.
string foo  = (row.IsDBNull(i  = row.GetOrdinal("Foo")) ? null : row.GetString(i));
int bar = (row.IsDbNull(i = row.GetOrdinal("Bar")) ? -1 : row.GetInt32(i));

इनलाइन असाइनमेंट भ्रामक हो सकता है यदि आपको नहीं पता कि यह वहां है, लेकिन यह पूरे ऑपरेशन को एक लाइन पर रखता है, जो मुझे लगता है कि पठनीयता को बढ़ाता है जब आप कोड के एक ब्लॉक में कई कॉलमों से गुणों को आबाद कर रहे हैं।


3
DataRow हालांकि IDataRecord को लागू नहीं करता है।
इलिटिरिटोर

5

ऐसा नहीं है कि मैंने ऐसा किया है, लेकिन आप लगभग डबल इंडेक्सर कॉल प्राप्त कर सकते हैं और फिर भी एक स्थिर / एक्सटेंशन विधि का उपयोग करके अपने कोड को साफ रख सकते हैं।

अर्थात।

public static IsDBNull<T>(this object value, T default)
{
    return (value == DBNull.Value)
        ? default
        : (T)value;
}

public static IsDBNull<T>(this object value)
{
    return value.IsDBNull(default(T));
}

फिर:

IDataRecord record; // Comes from somewhere

entity.StringProperty = record["StringProperty"].IsDBNull<string>(null);
entity.Int32Property = record["Int32Property"].IsDBNull<int>(50);

entity.NoDefaultString = record["NoDefaultString"].IsDBNull<string>();
entity.NoDefaultInt = record["NoDefaultInt"].IsDBNull<int>();

साथ ही अशक्त जाँच तर्क को एक स्थान पर रखने का लाभ है। निश्चित रूप से, यह एक अतिरिक्त विधि कॉल है।

सिर्फ एक विचार।


2
ऑब्जेक्ट पर एक विस्तार विधि जोड़ना बहुत व्यापक है, हालांकि। व्यक्तिगत रूप से मैंने DataRow पर एक विस्तार विधि पर विचार किया हो सकता है, लेकिन आपत्ति नहीं।
मार्क Gravell

यह सच है, हालांकि यह ध्यान रखें कि एक्सटेंशन विधियां केवल तब उपलब्ध होती हैं जब एक्सटेंशन क्लास के नाम स्थान को आयात किया जाता है।
रिचर्ड साज़ेले

5

मैं यथासंभव इस जांच से बचने की कोशिश करता हूं।

स्पष्ट रूप से उन स्तंभों के लिए किए जाने की आवश्यकता नहीं है जो पकड़ नहीं सकते हैं null

यदि आप एक अशक्त मान प्रकार ( int?, आदि) में संग्रहित कर रहे हैं , तो आप केवल उपयोग करके परिवर्तित कर सकते हैं as int?

आप के बीच अंतर करने की जरूरत नहीं है string.Emptyऔर null, आप बस फोन कर सकते हैं .ToString(), के बाद से DBNull वापस आ जाएगी string.Empty



4

यह है कि मैं DataRows से पढ़ने को कैसे संभालता हूं

///<summary>
/// Handles operations for Enumerations
///</summary>
public static class DataRowUserExtensions
{
    /// <summary>
    /// Gets the specified data row.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="dataRow">The data row.</param>
    /// <param name="key">The key.</param>
    /// <returns></returns>
    public static T Get<T>(this DataRow dataRow, string key)
    {
        return (T) ChangeTypeTo<T>(dataRow[key]);
    }

    private static object ChangeTypeTo<T>(this object value)
    {
        Type underlyingType = typeof (T);
        if (underlyingType == null)
            throw new ArgumentNullException("value");

        if (underlyingType.IsGenericType && underlyingType.GetGenericTypeDefinition().Equals(typeof (Nullable<>)))
        {
            if (value == null)
                return null;
            var converter = new NullableConverter(underlyingType);
            underlyingType = converter.UnderlyingType;
        }

        // Try changing to Guid  
        if (underlyingType == typeof (Guid))
        {
            try
            {
                return new Guid(value.ToString());
            }
            catch

            {
                return null;
            }
        }
        return Convert.ChangeType(value, underlyingType);
    }
}

उपयोग उदाहरण:

if (dbRow.Get<int>("Type") == 1)
{
    newNode = new TreeViewNode
                  {
                      ToolTip = dbRow.Get<string>("Name"),
                      Text = (dbRow.Get<string>("Name").Length > 25 ? dbRow.Get<string>("Name").Substring(0, 25) + "..." : dbRow.Get<string>("Name")),
                      ImageUrl = "file.gif",
                      ID = dbRow.Get<string>("ReportPath"),
                      Value = dbRow.Get<string>("ReportDescription").Replace("'", "\'"),
                      NavigateUrl = ("?ReportType=" + dbRow.Get<string>("ReportPath"))
                  };
}

करने के लिए रंगमंच की सामग्री दानव मेरे नेट गॉट ChageTypeTo कोड के लिए।


4

मैंने विस्तार विधियों के साथ कुछ ऐसा ही किया है। यहाँ मेरा कोड है:

public static class DataExtensions
{
    /// <summary>
    /// Gets the value.
    /// </summary>
    /// <typeparam name="T">The type of the data stored in the record</typeparam>
    /// <param name="record">The record.</param>
    /// <param name="columnName">Name of the column.</param>
    /// <returns></returns>
    public static T GetColumnValue<T>(this IDataRecord record, string columnName)
    {
        return GetColumnValue<T>(record, columnName, default(T));
    }

    /// <summary>
    /// Gets the value.
    /// </summary>
    /// <typeparam name="T">The type of the data stored in the record</typeparam>
    /// <param name="record">The record.</param>
    /// <param name="columnName">Name of the column.</param>
    /// <param name="defaultValue">The value to return if the column contains a <value>DBNull.Value</value> value.</param>
    /// <returns></returns>
    public static T GetColumnValue<T>(this IDataRecord record, string columnName, T defaultValue)
    {
        object value = record[columnName];
        if (value == null || value == DBNull.Value)
        {
            return defaultValue;
        }
        else
        {
            return (T)value;
        }
    }
}

इसका उपयोग करने के लिए, आप कुछ ऐसा करेंगे

int number = record.GetColumnValue<int>("Number",0)

4

यदि किसी DataRow में पंक्ति ["fieldname"] isDbNull इसे 0 से बदल दें अन्यथा दशमलव मान प्राप्त करें:

decimal result = rw["fieldname"] as decimal? ?? 0;

3
public static class DBH
{
    /// <summary>
    /// Return default(T) if supplied with DBNull.Value
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value"></param>
    /// <returns></returns>
    public static T Get<T>(object value)
    {   
        return value == DBNull.Value ? default(T) : (T)value;
    }
}

इस तरह का उपयोग करें

DBH.Get<String>(itemRow["MyField"])

3

मेरे पास एक प्रोग्राम में IsDBNull है जो एक डेटाबेस से बहुत सारा डेटा पढ़ता है। IsDBNull के साथ यह लगभग 20 सेकंड में डेटा लोड करता है। IsDBNull के बिना, लगभग 1 सेकंड।

इसलिए मुझे लगता है कि इसका उपयोग करना बेहतर है:

public String TryGetString(SqlDataReader sqlReader, int row)
{
    String res = "";
    try
    {
        res = sqlReader.GetString(row);
    }
    catch (Exception)
    { 
    }
    return res;
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.