DBNull চেক করার জন্য এবং তারপরে কোনও ভেরিয়েবলকে নির্ধারণ করার সবচেয়ে কার্যকরী উপায়?


151

এই প্রশ্নটি মাঝে মাঝে উঠে আসে তবে আমি সন্তোষজনক উত্তর দেখিনি seen

একটি সাধারণ প্যাটার্ন হ'ল (সারিটি একটি ডাটারো ):

 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?

এটি ইঙ্গিত করে যে .গেটটাইপ () দ্রুত হওয়া উচিত, তবে সম্ভবত সংকলকটি কিছু কৌশল জানেন যা আমি না?

দ্বিতীয় প্রশ্ন, সারি ["মান"] এর মানটি ক্যাশ করার মতো কি সংকলক সূচককে কোনওভাবেই অপ্টিমাইজ করে?

উদাহরণ স্বরূপ:

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

মন্তব্য:

  1. সারি ["মান"] বিদ্যমান।
  2. আমি কলামটির কলাম সূচক জানি না (সুতরাং কলামের নাম অনুসন্ধান)।
  3. আমি বিশেষত ডিবিএনল এবং তারপরে অ্যাসাইনমেন্ট পরীক্ষা করার বিষয়ে জিজ্ঞাসা করছি (অকাল অপটিমাইজেশন ইত্যাদি নয়)।

আমি কয়েকটি পরিস্থিতিতে বেঞ্চমার্ক করেছি (সেকেন্ডের মধ্যে সময়, 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

অবজেক্ট.রফারেন্সএকুয়ালসের পারফরম্যান্স "==" এর মতোই

সবচেয়ে আকর্ষণীয় ফলাফল? যদি আপনি কলামের নাম কেস অনুসারে মিলে না যায় (উদাহরণস্বরূপ, "মান" এর পরিবর্তে "মান", এটি প্রায় দশগুণ বেশি সময় নেয় (স্ট্রিংয়ের জন্য):

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

গল্পটির নৈতিক বলে মনে হচ্ছে আপনি যদি তার সূচী অনুসারে কোনও কলাম সন্ধান করতে না পারেন তবে নিশ্চিত হয়ে নিন যে আপনি যে কলামের নাম সূচককে খাওয়ান সেটি ডেটা কলামের নামের সাথে ঠিক মিলছে।

মানটি ক্যাচিং করা প্রায় দ্বিগুণ দ্রুত বলে মনে হয় :

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
সারিটি ডেটারো বা আইডিটাআরকর্ড / আইডিটাআরডার কিনা তা আপনি পরিষ্কার করতে পারেন?
মার্ক গ্র্যাভেল

7
এখন আমাদের আরও অনেক ভাল। নেট ফ্রেমওয়ার্ক রয়েছে এবং আমরা ডেটারো এক্সটেনশন পদ্ধতি ব্যবহার করতে পারি ।
পাভেল হোদেক

যদি আপনি কলামের নাম কেস অনুসারে মিলান না (উদাহরণস্বরূপ, "মান" এর পরিবর্তে "মান", এটি প্রায় দশগুণ বেশি সময় নেয় (একটি স্ট্রিংয়ের জন্য) এটি সম্পূর্ণরূপে বাস্তবায়নের উপর নির্ভর করে I আমি মনে করি এটি ক্ষেত্রে ছিল (পরিবর্তিত মাইএসকিউএল এডিও.এনইটি সংযোগকারী সহ কলামের নামটি অনেক ধীর হওয়ার ক্ষেত্রে) তবে স্কেল সার্ভার বা এসকিউএলাইটের জন্য এটি মোটেও নয় (মনে রাখবেন না) বিষয়গুলি এখন পরিবর্তিত হতে পারে Yes হ্যাঁ, সন্দেহের ভিত্তিতে মূল নির্দেশিকাটি অর্ডিনালে যেতে হবে।
নওফাল

@ পাভেলহোডেক এই জাতীয় লজ্জা যা কেবল ডেটা র এর জন্য। 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)বা পরিবর্তে অন্য কোনও বিকল্প।


কোনও সম্পর্কযুক্ত নোটে, স্টিভো 3000 এর পরামর্শের জন্য এখানে একটি 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)আপনি এটি ইতিমধ্যে একবার পড়ছেন এবং আবার এটি পড়ছেন। এটি না বলে পার্থক্য তৈরি করবে, তবে তাত্ত্বিকভাবে এটি কম দক্ষ হতে পারে ..
নওফাল

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
ঠিক আছে, উল্লিখিত সমস্ত বিকল্পগুলি কাঠামোর মধ্যে নির্মিত হয়েছে ... প্রকৃতপক্ষে, রূপান্তর করুন.আইএসডিবি নন আইকনভার্টেবল সম্পর্কিত অনেক অতিরিক্ত কাজ করে ...
মার্ক গ্র্যাভেল

1
এবং ক্যাশেটি পুনরায় করুন - আপনি যদি শর্তযুক্ত উদাহরণ দিয়ে বোঝাতে চান, না - এটি আসলে হওয়া উচিত নয় (এবং না)। এটি সূচককে দুবার কার্যকর করবে।
মার্ক গ্র্যাভেল

ওহ, এবং এই কোডটি সংকলন করে না - তবে তাদের মধ্যে একটিতে একটি (অন্তর্নি?) যুক্ত করুন এবং আপনি এর 2 টি (আইএল-এ) দেখতে পাবেন: কলভার্ট উদাহরণ বস্তু [সিস্টেম.ডাটা] সিস্টেম.ডাটা.ডাটাও :: get_Item (স্ট্রিং)
মার্ক গ্র্যাভেল

20

সংকলক সূচকটিকে অপ্টিমাইজ করবে না (যেমন আপনি যদি সারি ["মান"] দুবার ব্যবহার করেন), তাই হ্যাঁ এটি করা কিছুটা দ্রুত:

object value = row["value"];

এবং তারপরে দ্বিগুণ মান ব্যবহার করুন; .গেটটাইপ () ব্যবহার করে সমস্যাগুলি ঝুঁকিপূর্ণ হলে এটি ঝুঁকিপূর্ণ ...

DBNull.Valueআসলে একটি সিঙ্গেলটন, তাই চতুর্থ বিকল্প যুক্ত করতে - আপনি সম্ভবত রেফারেন্সএকুয়ালগুলি ব্যবহার করতে পারেন - তবে বাস্তবে, আমি মনে করি আপনি এখানে খুব বেশি চিন্তিত হচ্ছেন ... "আমি", "==" এর মধ্যে গতি আলাদা বলে আমি মনে করি না "ইত্যাদি আপনি যে কোনও পারফরম্যান্স সমস্যার কারণ হিসাবে দেখছেন। আপনার সম্পূর্ণ কোডটির প্রোফাইল দিন এবং গুরুত্বপূর্ণ কিছুতে ফোকাস করুন ... এটি এটি হবে না।


2
কার্যত সমস্ত ক্ষেত্রে == রেফারেন্সএকুয়ালসের সমতুল্য হতে চলেছে (উদাহরণস্বরূপ, ডিবিএনল) এবং এটি অনেক বেশি পাঠযোগ্য। আপনি চাইলে @ মার্ক গ্র্যাভেলের অপ্টিমাইজেশন ব্যবহার করুন তবে আমি তার সাথে আছি - সম্ভবত খুব বেশি সাহায্য করবে না। বিটিডাব্লু, রেফারেন্স সমতা সর্বদা টাইপ চেকিং বীট করা উচিত।
tvanfosson

1
এখন পুরানো, তবে আমি সম্প্রতি বেশ কয়েকটি কেস দেখেছি যেখানে প্রোফাইলার ঠিক করতে ঠিক বলেছেন said বড় ডেটা সেটগুলি মূল্যায়নের কল্পনা করুন, যেখানে প্রতিটি ঘরে এই চেক করা দরকার to এটি অপ্টিমাইজ করা বড় পুরষ্কার কাটাতে পারে। তবে উত্তরের গুরুত্বপূর্ণ অংশটি এখনও ভাল: প্রথমে প্রোফাইলটি , আপনার সময়টি কোথায় ব্যয় করা ভাল তা জানতে to
জোয়েল কোহোর্ন

আমার ধারণা, এলভিস অপারেটরের সি # 6 পরিচিতি আপনাকে প্রস্তাবিত চেকটিতে নাল রেফারেন্স ব্যতিক্রম এড়াতে সহজ করে তোলে। মান .GetType () == typeof (DBNull)?
Eniola

হ্যা আমি রাজি. সাধারণত যাবার একটি ভাল উপায় তবে যারা ব্যবহার করতে চান না তাদের জন্য .GetType () যার ঝুঁকি আপনি চিহ্নিত করেছেন, তাহলে?। এটির চারপাশে একটি উপায় সরবরাহ করে।
এনিওলা

9

আমি সি # তে নিম্নলিখিত কোডগুলি ব্যবহার করব ( ভিবি.এনইটি এত সহজ নয়)।

কোডটি নাল / ডিবিএন না হলে মান নির্ধারিত করে, অন্যথায় এটি ডিফল্টকে স্বীকৃতি দেয় যা সংকলককে নির্ধারিত অবহেলা করার অনুমতি দিয়ে এলএইচএস মান নির্ধারণ করতে পারে।

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/...
stevehipwell

এবং আবারও, নিজের কম্পিউটার থেকে দূরে থাকাকালীন একটি এসও প্রশ্নে মন্তব্য করা (এটিতে ডিভ সরঞ্জামগুলি সহ) ভুল প্রমাণিত হয়েছে! তুমি ঠিক; আমি অবাক হয়ে শিখেছি যে ধরণের জন্য TryCastসি # এর asঅপারেটরের মতো সুবিধাজনক কার্যকারিতা সরবরাহ করে না Nullable(Of T)। আমি এটি অনুকরণ করার সবচেয়ে নিকটতম উপায়টি হ'ল আপনার নিজের ফাংশনটি লিখি, যেমনটি আমি এখন আমার উত্তরে বলেছি।
ড্যান তাও

এটিকে জেনেরিক পদ্ধতিতে পুনরায় সংশোধন করতে আপনার পক্ষে শক্ত সময় হবে এবং আপনি যদি তা করেন তবে খুব বেশি জড়িত কাস্টিং এটিকে কম দক্ষ করে তোলেন।
নওফাল

8

আমি মনে করি এখানে খুব কম পদ্ধতিরই সম্ভাবনা ওপিকে সবচেয়ে বেশি উদ্বেগের ঝুঁকি দেয় না (মার্ক গ্রাভেল, স্টিভো 3000, রিচার্ড জাজালিয়া, নীল, ড্যারেন কোপ্প্যান্ড) এবং বেশিরভাগ অহেতুক জটিল। এটি অকেজো মাইক্রো-অপ্টিমাইজেশন সম্পূর্ণরূপে সচেতন হওয়া, আমাকে বলতে দাও যে আপনার মূলত এগুলি নিযুক্ত করা উচিত:

1) DataReader / DataRow থেকে দুবার মানটি পড়বেন না - সুতরাং নাল চেক এবং ক্যাসট / রূপান্তরগুলির আগে এটি ক্যাশে করুন বা record[X]যথাযথ স্বাক্ষর সহ কোনও কাস্টম এক্সটেনশন পদ্ধতিতে আপনার অবজেক্টকে সরাসরি উত্তোলন করুন ।

২) উপরের কথা মেনে চলার জন্য, IsDBNullআপনার ডাটাআরডার / ডাটাআরউতে record[X]অভ্যন্তরীণভাবে কল করার কারণে বিল্ট ফাংশনটি ব্যবহার করবেন না , ফলস্বরূপ আপনি এটি দুটিবার করবেন।

3) টাইপ তুলনা একটি সাধারণ নিয়ম হিসাবে মান তুলনা তুলনায় সর্বদা ধীর হবে। শুধু record[X] == DBNull.Valueআরও ভাল করুন।

৪) ডাইরেক্ট কাস্টিং Convertরূপান্তরকরণের জন্য ক্লাস কল করার চেয়ে দ্রুততর হবে , যদিও আমি আশঙ্কা করি যে পরবর্তীকালে কম ফল হবে।

5) শেষ অবধি, কলামের নামের চেয়ে সূচী দ্বারা রেকর্ড অ্যাক্সেস করা আরও দ্রুত হবে।


আমি মনে করি স্জলে, নীল এবং ড্যারেন কোপপাণ্ডের পদ্ধতির দিকে যাওয়া আরও ভাল হবে। আমি বিশেষত ড্যারেন কোপ্প্যান্ডের এক্সটেনশন পদ্ধতি পদ্ধতির পছন্দ করি যা গ্রহণ করে IDataRecord(যদিও আমি এটিকে আরও সংকুচিত করতে চাই IDataReader) এবং সূচক / কলামের নাম।

এটিকে কল করতে যত্ন নিন:

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

এবং না

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

যদি আপনি মধ্যে পার্থক্য করতে প্রয়োজন 0এবং DBNull। উদাহরণস্বরূপ, যদি আপনার এনাম ক্ষেত্রগুলিতে নাল মান default(MyEnum)থাকে তবে অন্যথায় প্রথম এনাম মান ফেরত আসার ঝুঁকি থাকে। তাই আরও ভাল কল record.GetColumnValue<MyEnum?>("Field")

আপনি যদি একটি থেকে পড়া করছি যেহেতু DataRow, আমি উভয় জন্য এক্সটেনশন পদ্ধতি তৈরি করবে DataRowএবং IDataReaderএর দ্বারা শোষক সাধারণ কোড।

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দীর্ঘ রান, ইত্যাদি পদ্ধতি। আপনি যদি ডিবিটি ডিফল্টরূপে স্ট্রিং পড়তে বা 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);
}

স্টিভো 3000 এর পদ্ধতির সাথে, আমি কলটিটিটিকে কিছুটা কুৎসিত ও ক্লান্তিকর বলে মনে করি এবং এর থেকে জেনেরিক কাজ করা আরও কঠিন হবে।


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

আমি ব্যক্তিগতভাবে এই বাক্য গঠনটি সমর্থন করি, যা স্পষ্টভাবে প্রকাশিত ইসডিবিএন পদ্ধতি ব্যবহার করে 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);
}

ড্যাল কোডে সংযোগের জন্য একক লাইনে ফিট করার জন্য আবারও লিখেছিলেন - নোট করুন যে এই উদাহরণে আমরা নির্ধারণ করছি 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
যদিও অবজেক্টে এক্সটেনশন পদ্ধতি যুক্ত করা খুব বিস্তৃত। ব্যক্তিগতভাবে আমি ডেটারোতে একটি এক্সটেনশন পদ্ধতিটি বিবেচনা করেছি, তবে আপত্তি নেই not
মার্ক গ্রেভেল

সত্য, যদিও মনে রাখবেন যে এক্সটেনশন শ্রেণিগুলির নামস্থান আমদানি করা হলে কেবল এক্সটেনশন পদ্ধতিগুলি উপলভ্য।
রিচার্ড জাজলে 21

5

আমি যতটা সম্ভব এই চেকটি এড়াতে চেষ্টা করি।

স্পষ্টতই যে কলামগুলি ধরে রাখতে পারে না তার জন্য কাজ করার দরকার নেই null

আপনি যদি কোনও নুলযোগ্য মান ধরণের ( int?ইত্যাদি) সঞ্চয় করে থাকেন তবে আপনি কেবল ব্যবহার করে রূপান্তর করতে পারেন as int?

আপনার যদি string.Emptyএবং এর মধ্যে পার্থক্য করার প্রয়োজন না হয় তবে আপনি nullকেবল কল করতে পারেন .ToString(), যেহেতু ডিবিএনল ফিরে আসবে string.Empty



4

এইভাবে আমি ডেটাআরগুলি থেকে পঠন পরিচালনা করি

///<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"))
                  };
}

দানবদের কাছে প্রপস আমার । নেটটি চেজটাইপটো কোডের জন্য পান।


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

যদি একটি ডাটাআর সারিতে ["ক্ষেত্রের নাম"] হয় তবে DbNull 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

আমার একটি প্রোগ্রামে ইসডিবিএনল রয়েছে যা একটি ডাটাবেস থেকে প্রচুর ডেটা পড়ে। আইএসডিবিউনুল দিয়ে এটি প্রায় 20 সেকেন্ডের মধ্যে ডেটা লোড করে। ইসডিবিএনল ছাড়া, প্রায় 1 সেকেন্ড।

সুতরাং আমি মনে করি এটি ব্যবহার করা ভাল:

public String TryGetString(SqlDataReader sqlReader, int row)
{
    String res = "";
    try
    {
        res = sqlReader.GetString(row);
    }
    catch (Exception)
    { 
    }
    return res;
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.