none
בעיה בשאילתת delete RRS feed

  • שאלה

  • אני מנסה לעשות בדף מנהל אפשרות למחוק משתמשים רשומים. 

    אני לוקח את השם משתמש שלהם ובונה את שאילתת המחיקה, מתחבר למסד נתונים כותב:

    int rowsAffected;

            SqlConnection connection = new SqlConnection(ConnectionString());

            SqlCommand command = new SqlCommand(strSql, connection);

            connection.Open();

            rowsAffected = command.ExecuteNonQuery();

            connection.Close();

    והוא כותב לי שגיאה: לא נמצאה העמודה ואז הוא כותב לי את השם משתמש ומסמן לי את השורה

      rowsAffected = command.ExecuteNonQuery() בשגיאה

    מה לעשות?

    יום שני 13 יוני 2011 14:05

תשובות

  • אהלן Chaim Kedem

    קודם כל כל הכבוד :-) הקדמת אותי בדקה בשליחת התשובה בזמן שכתבתי את התשובה אתה שלחת את התגובה שלך אבל יש לי  הרגשה שמי ששאל את השאלה שכח בכלל לבדוק את התשובות.

    שמתי לב כרגע למה שכתבת קצת יותר לעומק ואם תרשה לי לזרוק 2 נקודות קטנות:

    1. כמו שכתבתי בתשובה שלי חסרים לו מרחאות שסוגרות את המשתנה ולא רק בצד אחד. גם בפתיחה וגם בסגירה של הערך הטקסטואלי חסרות לו מרחאות

    גם לך חסר בפקודה המרחאות אחרי המשתנה :-)
    בכתיבה בצורה שאתה כתבת הרבה יותר קל לראות בעיות ואכן מומלץ לכתוב כך אבל זה בדיוק כמו לשרשת את הפרמטר בתוך ה String

    2. לגבי מה שכתבת בפקודה:

    string sql =
     string.Format(
      "DELETE FROM tblUsers WHERE (userName = '{0})"
      , userName
    );

     

    בשום אופן זה לא כתיבה יותר "תקנית" לרשום את המשתנה בנפרד. זו אולי כתיבה יותר קלה לקריאה או לכתיבה אבל לא יותר נכונה ובטח שלא קשורה לשום תקן

    מה שמעלה את העובדה שזו כתיבה לא טובה לגבי פרמטרים בשרשרת שאילתה. זו פירצת אבטחה כפי שכתבתי (אבל זה נושא אחר)



    • סומן כתשובה על-ידי Meir Pinto יום רביעי 22 יוני 2011 11:20
    שבת 18 יוני 2011 13:39
    מנחה דיון

כל התגובות

  • הי,

    אתה יכול לצרף את השאילתא שאתה שולח ב- command?

    נראה לי שיש לך שם שגיאה בשירשור של הפרמטרים או שאתה מפנה לעמודה שלא קיימת בטבלה.


    אסף שלם
    יום שני 13 יוני 2011 14:12
  • היי.

    אי אפשר לענות באמת בלי לראות את השאילתא.

    יכול להיות כמה דברים:

    • פנייה לעמודה שאכן אינה קיימת - כתוצאה משגיאה בהכנת השאילתא (כמו שאסף רשם).
    • שגיאת כתיב.
    • פנייה ל-DB לא נכון (שגיאה ב-connection string אולי).
    • וכדו'....

    itaigitt, http://copypastenet.blogspot.com
    יום שני 13 יוני 2011 14:21
  • "DELETE FROM tblUser WHERE (userName='"+userName+"')";
    יום שני 13 יוני 2011 15:24
  • המופע של המחלקה SqlConnection  הוגדר בשורה הבאה:

    SqlConnection connection = new SqlConnection(ConnectionString

    הקישור למסד הנתונים נפתח בהצלחה בשורה הבאה:

    connection.Open();

    מסקנה: הבעיה אינה קשורה להתחברות למסד הנתונים ככל הנראה אלא בשאילתה/הפעלת השאילתה

    1. ניטור במקרה זה יהיה קודם כל לנסות להריץ את השאילתה ישירות ב SSMS
    ניטור זה יזהה לנו בעיות בשאילתה עצמה או בהפעלת השאילתה ברמת ה SQL כגון מקרים של ניסיון ל מחוק נתון מקושר (ראה הערה 2 למטה)

    2. היה והרצת השאילתה מצליח בצורה ישירה אז נשאר לבדוק את נושא הפעלת השאילתה דרך הקוד. כאן נכנס למשל מה שכתב אסף: שרשור פרמטרים לא נכון (ראה הערה: 1 למטה). אפשרות נוספת היא למשל בעיה בהפעלת הכנסת תוצאת השאילתה למשתנה (ראה הערה 5 למטה). ויש עוד אפשרויות פחות נפוצות

    הערה 1: היה ונעשה שרשור פרמטרים זו צורת כתיבה גרועה ופרצת אבטחה חמורה מאוד אבל זה נושא אחר
    הערה 2: בדוט נט קיים אובייקט ניהול משמשים מובנה. אובייקט זה עובד בדומה לאופן ניהול המשתמשים תחת AD. כאשר ישנה טבלה של חוקים וטבלה של משתמשים. נסיון למחוק משתמש בצורה ישירה שלא דרך אובייקט המשתמשים של דוט נט לא יתאפשר אם המשתמש מקושר לחוק כלשהו (קשר רגיל של מפתח חיצוני הפונה למפתח ראשי).
    הערה 3: ניתן לקבל ברמת האפליקציה את השגיאה של ה SQL בעזרת עבודה עם Exception ייחודי בשם: SqlException
    נתון זה ייחזיר את תוצאת השגיאה כפי שאנו רואים ב SSMS
    הערה 4: דיברנו לפני יומיים על נושא מטאדטא :-) זהו סוג של מטאדטא. מידע על המידע של האפליקציה החיצונית שלנו (ה SQL אליו פנינו מהאפליקציה שלנו). לכן שיטת הדיבאג שהוצגה שם בשירשור יכולה לעזור כאן למשל.
    הערה 5 : ExecuteNonQuery מחזיר לאחר ביצוע הפעולה את מספר הרשומות שהושפעו במקרה שהכל הצליח. בדרך כלל לא מפעילים אותו על ידי קביעת משתנה ששווה לתוצאה שלו אלא רק על ידי הרצה שלו ישירות למשל:

    command.ExecuteNonQuery()

    אם מכניסים את הנתון החוזר למשתנה יש לוודא התאמה של סוג המשתנה כמובן או לבצע המרה מתאימה (אני תמיד ממיר ל String במקרה זה)

    וכמובן כמו שכתבו קודמיי בלי לראות את הקוד אנחנו לא יכולים לבדוק


    • נערך על-ידי pituachMVP, Editor יום שני 13 יוני 2011 17:03 תיקון המספור של ההערות :-)
    יום שני 13 יוני 2011 15:51
    מנחה דיון
  • using System;
    using System.Data;
    using System.Configuration;
    using System.Collections;
    using System.Web;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using System.Web.UI.HtmlControls;
    using System.Data.SqlClient;
    public partial class Delete : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (Session["user"] == null)
            {
                Response.Redirect("Index.aspx");
            }
            string userName = Request.QueryString["userName"].ToString();
            string sql = string.Format("DELETE FROM tblUsers WHERE (userName = " + userName + ")");
            ExecuteNonQuery(sql);
            Response.Redirect("ManagerPage.aspx");
        }
        private string ConnectionString()
        {
            return @"Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\dbUsers.mdf;Integrated Security=True;User Instance=True";
        }
        public int ExecuteNonQuery(string strSql)
        {
            int rowsAffected;
            SqlConnection connection = new SqlConnection(ConnectionString());
            SqlCommand command = new SqlCommand(strSql, connection);
            connection.Open();
            rowsAffected = command.ExecuteNonQuery();
            connection.Close();
            return rowsAffected;
        }
    }
    יום שני 13 יוני 2011 16:12
  • השורה הזו בעייתית

       string sql = string.Format("DELETE FROM tblUsers WHERE (userName = " + userName + ")");

    חסר גרש בתחילת שם המשתמש ובסופו.

    ואני גם לא מבין מה חסר לך שם הstring.Format.

       string sql = string.Format("DELETE FROM tblUsers WHERE (userName = '{0})", userName);

    אם אתה רוצה לכתוב תקין, תכתוב את השורה שכתבתי.

     

    בהצלחה.

    יום שני 13 יוני 2011 16:47
  •  

    חבל שאתה לא פועל בשיטת הניטור שהצעתי
    זה יכוון אותך למצוא את הבעיה לבד :-(

    בכל מקרה בקוד חסר לך פשוט מרחאות שסוגרות את השם משתמש בתוך השאילתה. שם המשתמש הוא שרשרת ולכן צריך להיות בתוך השאילתה של ה SQL בתוך מרחאות בודדות.

    במקום:
    string sql = string.Format("DELETE FROM tblUsers WHERE (userName = " + userName + ")");

    תרשום
    string sql = string.Format("DELETE FROM tblUsers WHERE (userName = '" + userName + "')");

    אם תנטר את כמו שכתבתי תוכל לוודא שאין עוד שגיאות בקלות. בכלל אני ממליץ תמיד בכתיבת קוד באפליקציה שעושה שימוש בשאילתה קודם לבדוק את השאילתה ישירות ב SQL :-)


    **** חשוב מאוד!

    קרא את ההערה מספר 1 שכתבתי קודם! הקוד שלך גרוע מאוד ואתה פותח פירצת אבטחה חמורה ללא שום סיבה. לעולם אל תשרשר פרמטרים אלא תעשה שמוש בפרמטרים. לא סתם זה משהו מובנה באוביקט SqlCommand



    • נערך על-ידי pituachMVP, Editor יום שישי 17 יוני 2011 08:13 שיעמום: הוספת הבלטה למקטע בהודעה
    יום שני 13 יוני 2011 16:48
    מנחה דיון
  • אהלן Chaim Kedem

    קודם כל כל הכבוד :-) הקדמת אותי בדקה בשליחת התשובה בזמן שכתבתי את התשובה אתה שלחת את התגובה שלך אבל יש לי  הרגשה שמי ששאל את השאלה שכח בכלל לבדוק את התשובות.

    שמתי לב כרגע למה שכתבת קצת יותר לעומק ואם תרשה לי לזרוק 2 נקודות קטנות:

    1. כמו שכתבתי בתשובה שלי חסרים לו מרחאות שסוגרות את המשתנה ולא רק בצד אחד. גם בפתיחה וגם בסגירה של הערך הטקסטואלי חסרות לו מרחאות

    גם לך חסר בפקודה המרחאות אחרי המשתנה :-)
    בכתיבה בצורה שאתה כתבת הרבה יותר קל לראות בעיות ואכן מומלץ לכתוב כך אבל זה בדיוק כמו לשרשת את הפרמטר בתוך ה String

    2. לגבי מה שכתבת בפקודה:

    string sql =
     string.Format(
      "DELETE FROM tblUsers WHERE (userName = '{0})"
      , userName
    );

     

    בשום אופן זה לא כתיבה יותר "תקנית" לרשום את המשתנה בנפרד. זו אולי כתיבה יותר קלה לקריאה או לכתיבה אבל לא יותר נכונה ובטח שלא קשורה לשום תקן

    מה שמעלה את העובדה שזו כתיבה לא טובה לגבי פרמטרים בשרשרת שאילתה. זו פירצת אבטחה כפי שכתבתי (אבל זה נושא אחר)



    • סומן כתשובה על-ידי Meir Pinto יום רביעי 22 יוני 2011 11:20
    שבת 18 יוני 2011 13:39
    מנחה דיון
  • היי,

    אשמח אם תוכל/י לעדכן אותנו בסטטוס השאלה שלך.

     

    במידה וקיבלת תשובה מתאימה לשאלתך, יש לסמן את התשובה המתאימה ע"י לחיצה על "סמן כתשובה" ליד סימון ה V הירוק

    אם לא קיבלת תשובה, מומלץ לספק פרטים נוספים אודות הבעיה, פרטי לוג, צילומי מסך וכו'

    על מנת להעלות תמונה לפורום ניתן להעזר במדריך להעלאת תמונה.


    אם תגובתי פתרה את בעייתך - לחץ/י, על "סמן כתשובה" ליד סימן ה V הירוק.

    על מנת להעלות תמונה לפורום ניתן להעזר במדריך להעלאת תמונה
    מיקרוסופט מציעה שירות זה ללא תשלום, למטרת סיוע למשתמשים והעשרת הידע הקשור בטכנולוגיות ובמוצרים של Microsoft. תוכן זה מתפרסם כפי שהוא והוא אינו מעיד על כל אחריות מצד מיקרוסופט.
    יום שלישי 21 יוני 2011 13:14