سؤال

في كثير من الأحيان ، يتعين علي التعامل مع DataTables المتصلة بعناصر التحكم في الشبكة ، ويبدو أن التحديث المخصص دائمًا ينتج عنه الكثير من التعليمات البرمجية المتعلقة بـ dbnull.value. رأيت سؤالًا مشابهًا هنا ولكن أعتقد أنه يجب أن يكون هناك إجابة أفضل:

ما هي أفضل طريقة للتعامل مع DBNULL

الشيء الذي أجده هو أنني أميل إلى تغليف تحديثات قاعدة البيانات الخاصة بي في الأساليب ، لذلك انتهى بي الأمر برمز مثل أدناه حيث أقوم بنقل dbnull.value إلى نوع لاغال ثم أعود للتحديث:

private void UpdateRowEventHandler(object sender, EventArgs e)
{
    Boolean? requiresSupport = null;
    if (grdMainLevel1.GetFocusedRowCellValue(colASRequiresSupport) != DBNull.Value)
        requiresSupport = (bool)grdMainLevel1.GetFocusedRowCellValue(colASRequiresSupport);

    AdditionalSupport.UpdateASRecord(year, studentID, requiresSupport)
}

internal static void UpdateASRecord(
        string year,
        string studentID,            
        bool? requiresSupport)
    {
        List<SqlParameter> parameters = new List<SqlParameter>();

        parameters.Add(new SqlParameter("@year", SqlDbType.Char, 4) { Value = year });
        parameters.Add(new SqlParameter("@student_id", SqlDbType.Char, 11) { Value = studentID });

        if (requiresSupport == null)
            parameters.Add(new SqlParameter("@requires_support", SqlDbType.Bit) { Value = DBNull.Value });
        else
            parameters.Add(new SqlParameter("@requires_support", SqlDbType.Bit) { Value = requiresSupport });

        //execute sql query here to do update
    }

كان ذلك مجرد مثال على التدفق وليس رمز العمل. أدرك أنه يمكنني القيام بأشياء مثل تمرير الكائنات أو ابتلاع مشكلات الصب المحتملة باستخدام "كنوع" للحصول على DBULL مباشرة إلى الفارغ ، لكن يبدو أن كلاهما يخفي أخطاء محتملة ، أحب نوع السلامة من الطريقة ذات الأنواع المخلوطة.

هل هناك طريقة أنظف للقيام بذلك مع الحفاظ على سلامة النوع؟

هل كانت مفيدة؟

المحلول

قد تركز اثنين من طرق المساعد العامة البسيطة (على الأقل على الاختبار في قطعة واحدة من الكود:

static T FromDB<T>(object value)
{
    return value == DBNull.Value ? default(T) : (T)value;
}

static object ToDB<T>(T value)
{
    return value == null ? (object) DBNull.Value : value;
}

يمكن بعد ذلك استخدام هذه الطرق عند الاقتضاء:

private void UpdateRowEventHandler(object sender, EventArgs e)
{
    AdditionalSupport.UpdateASRecord(year, studentID, 
        FromDB<Boolean?>(grdMainLevel1.GetFocusedRowCellValue(colASRequiresSupport)));
}

internal static void UpdateASRecord(
        string year,
        string studentID,
        bool? requiresSupport)
{
    List<SqlParameter> parameters = new List<SqlParameter>();

    parameters.Add(new SqlParameter("@year", SqlDbType.Char, 4) { Value = year });
    parameters.Add(new SqlParameter("@student_id", SqlDbType.Char, 11) { Value = studentID });
    parameters.Add(new SqlParameter("@requires_support", SqlDbType.Bit) { Value = ToDB(requiresSupport) });

    //execute sql query here to do update
}

نصائح أخرى

لا أرى ما هو الخطأ as-بث و null ائتلاف.

asيتم استخدام البث للقراءة:

bool? requiresSupport =
  grdMainLevel1.GetFocusedRowCellValue(colASRequiresSupport) as bool?;
AdditionalSupport.UpdateASRecord(year, studentID, requiresSupport);

null يستخدم الفحم للكتابة:

parameters.Add(new SqlParameter("@student_id", SqlDbType.Char, 11)
  { Value = studentID });
parameters.Add(new SqlParameter("@requires_support", SqlDbType.Bit)
  { Value = (object)requiresSupport ?? DBNull.Value });

كلاهما هما نوعان من الأنواع ولا "يخفيون" أخطاء.

إذا كنت تريد حقا ، أنت يستطيع لفها في طرق ثابتة ، لذلك ينتهي بك الأمر للقراءة:

//bool? requiresSupport =
//  grdMainLevel1.GetFocusedRowCellValue(colASRequiresSupport) as bool?;
bool? requiresSupport = FromDBValue<bool?>(
  grdMainLevel1.GetFocusedRowCellValue(colASRequiresSupport));

وهذا للكتابة:

//parameters.Add(new SqlParameter("@requires_support", SqlDbType.Bit)
//  { Value = (object)requiresSupport ?? DBNull.Value });
parameters.Add(new SqlParameter("@requires_support", SqlDbType.Bit)
  { Value = ToDBValue(requiresSupport) });

رمز الطريقة الثابتة أكثر نظافة في حالة الكتابة ، لكن النية أقل وضوحًا (خاصة في حالة القراءة).

parameters.Add("@requires_support", SqlDbType.Bit).Value = (object)requiresSupport ?? DBNull.Value;

وهو ما يعني نفس الشيء

parameters.Add("@requires_support", SqlDbType.Bit).Value = (requiresSupport != null) ? (object)requiresSupport : DBNull.Value;

أو

if (requiresSupport != null)
    parameters.Add("@requires_support", SqlDbType.Bit).Value = requiresSupport 
else
    parameters.Add("@requires_support", SqlDbType.Bit).Value = DBNull.Value;

(يلزم طاقم إضافي إلى الكائن لإزالة غموض النوع)

public static object DbNullable<T>(T? value) where T : struct
{
    if (value.HasValue)
    {
        return value.Value;
    }
    return DBNull.Value;
}

public static object ToDbNullable<T>(this T? value) where T : struct
{
    return DbNullable(value);
}

هذا هو تنفيذي للمساعد DBNULL. الاستخدام بسيط:

new SqlParameter("Option1", option1.ToDbNullable())
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top