0

このクエリを書くのに行き詰まっています。私はこれらのテーブルを持っています:

料理:
CuisineID
CuisineName
CuisineType

料理:
DishID
DishName
CuisineID

施設:
施設 ID
施設名

RestaurantDish: RestaurantDishID RestaurantID DishID

レストラン: RestaurantID Name City Location PhoneNo

ユーザーが選択した施設や料理、または料理に応じてレストランを表示する必要があります。レストランのリストを取得したら、ユーザーが選択するたびに同じリストをさらに絞り込む必要があります。私は動作していないこのsted手順を書きました:

          ALTER PROCEDURE [dbo].[spGetFilterData]
@searchText NVARCHAR(MAX),
@DishIDs NVARCHAR(200) ,
@FacilitDs NVARCHAR(200) ,
@CuisineIDs NVARCHAR(200)
 AS 
BEGIN

    SET NOCOUNT ON;

    DECLARE @sql NVARCHAR(MAX)
    SET @sql = '';

    SET @sql = 'SELECT  RestaurantID ,
            Name ,
            City ,
            Location ,
            Country ,
            PhoneNo1 ,
            PhoneNo2 ,
            PhoneNo3 ,
            FaxNumber ,
            Timings ,
            HappyHour ,
            Menu ,
            Buffet ,
            Rating ,
            DateCreated ,
            Datemodified ,
            DateDeleted
    FROM    dbo.Restaurants AS r
    WHERE   ( RestaurantID IN (
              SELECT    rd.RestaurantID
              FROM      dbo.RestaurantDish AS rd
                        INNER JOIN dbo.Dishes1 AS d ON d.DishID = rd.DishID
              WHERE     ( d.DishName LIKE ''%' + @searchText + '%'''

    IF @DishIDs <> '' 
        BEGIN
            SET @sql =@sql + '   AND d.DishID IN ( ' + @DishIDs + ' )'

        END 
    SET @sql =@sql + ') ) )'       
    SET @sql =@sql + ' AND ( RestaurantID IN (
                 SELECT rf.RestaurantID
                 FROM   dbo.RestaurantFacility AS rf
                        INNER JOIN dbo.Facilities1 AS f ON f.FacilityID = rf.FacilityID
                 WHERE  ( f.FacilityName LIKE ''%' + @searchText + '%'''
    IF @FacilitDs <> '' 
        BEGIN
            SET @sql =@sql + ' AND f.FacilityID IN ( ' + @FacilitDs + ' )'
        END
    SET @sql =@sql + ') ) )'  
    SET @sql =@sql + '  OR ( RestaurantID IN (
                 SELECT RestaurantID
                 FROM   dbo.RestaurantDish
                 WHERE  ( DishID IN (
                          SELECT    dbo.RestaurantDish.DishID
                          FROM      dbo.Cuisine1
                          WHERE     ( CuisineName LIKE ''%' + @searchText
        + '%'')'
    IF @CuisineIDs <> '' 
        BEGIN
            SET @sql = @sql +' AND CuisineID IN ( ' + @CuisineIDs + ' )'
        END
    SET @sql =@sql + ') ) ))'                         
    SET @sql =@sql + '  OR ( Name LIKE ''%' + @searchText + '%'')
            OR ( City LIKE ''%' + @searchText + '%'')
            OR ( Country LIKE ''%' + @searchText + '%'')
            OR ( Buffet LIKE ''%' + @searchText + '%'')
            OR ( Location LIKE ''%' + @searchText + '%'')'
    EXECUTE sp_executesql @sql;     
END

私は他に何をすべきかわからない..これは私のクラスです:

         public class DBAccess
       {
        public DBAccess()
       {
    //
    // TODO: Add constructor logic here
    //
        }
private SqlConnection GetConnection()
{
    SqlConnection con = null;
    try
    {
        string strCon = ConfigurationManager.ConnectionStrings["food4uConnectionString"].ConnectionString;
        con = new SqlConnection(strCon);
        con.Open();

    }
    catch (Exception ex)
    {
        con.Close();
        throw;
    }
    return con;
}

public List<Restaurants> GetAllRestaurents(string searchText, string dishIDs, string facilityIDs, string cuisineIDS)
{
    List<Restaurants> restaurants = null;
    try
    {
        SqlCommand cmd = new SqlCommand("spGetFilterData", GetConnection());
        cmd.CommandType = System.Data.CommandType.StoredProcedure;

        cmd.Parameters.AddWithValue("searchText", searchText);
        cmd.Parameters.AddWithValue("DishIDs", dishIDs);
        cmd.Parameters.AddWithValue("FacilitDs", facilityIDs);
        cmd.Parameters.AddWithValue("CuisineIDs", cuisineIDS);

        SqlDataReader dreader = cmd.ExecuteReader();
        restaurants = new List<Restaurants>();
        while (dreader.Read())
        {
            restaurants.Add(new Restaurants()
            {
                RestaurantID = (int)dreader["RestaurantID"],
                Name = (string)dreader["Name"],
                City = (string)dreader["City"],
                Country = (string)dreader["Country"],
                Location = (string)dreader["Location"],
                PhoneNo1 = (string)dreader["PhoneNo1"],
                PhoneNo2 = (string)dreader["PhoneNo2"],
                PhoneNo3 = (string)dreader["PhoneNo3"],
                Menu = (string)dreader["Menu"],
                HappyHour = (string)dreader["HappyHour"],
                Buffet = (string)dreader["Buffet"],
                Rating = (string)dreader["Rating"],
                FaxNo = (string)dreader["FaxNumber"],
                Timings = (DateTime)dreader["Timings"],
                DateCreated = (DateTime)dreader["DateCreated"],
                DateDeleted = (DateTime)dreader["DateDeleted"],
                Datemodified = (DateTime)dreader["DateModified"]
            });
        }
    }
    catch (Exception ex)
    {
        throw;
    }

    return restaurants;
}

public List<Facilities1> GetFacilities(int restaurentID, string facilityID)
{
    List<Facilities1> facilities = null;
    try
    {
        SqlCommand cmd = new SqlCommand("spGetFacilities", GetConnection());
        cmd.CommandType = System.Data.CommandType.StoredProcedure;
        cmd.Parameters.AddWithValue("RestaurantID", restaurentID);
        cmd.Parameters.AddWithValue("FacilityID", facilityID);
        SqlDataReader dreader = cmd.ExecuteReader();
        facilities = new List<Facilities1>();
        while (dreader.Read())
        {
            facilities.Add(new Facilities1()
            {
                FacilityID = (int)dreader["FacilityID"],
                FacilityName = (string)dreader["FacilityName"]
            });
        }
    }
    catch (Exception ex)
    {
        throw;
    }

    return facilities;
}

public List<Dishes1> GetDishes(int restaurentID, string dishID)
{
    List<Dishes1> dishes = null;
    try
    {
        SqlCommand cmd = new SqlCommand("spGetDishes", GetConnection());
        cmd.CommandType = System.Data.CommandType.StoredProcedure;
        cmd.Parameters.AddWithValue("RestaurantID", restaurentID);
        cmd.Parameters.AddWithValue("DishID", dishID);
        SqlDataReader dreader = cmd.ExecuteReader();
        dishes = new List<Dishes1>();
        while (dreader.Read())
        {
            dishes.Add(new Dishes1()
            {
                DishID = (int)dreader["DishID"],
                DishName = (string)dreader["DishName"],
                Price = (int)dreader["Price"]
            });
        }
    }
    catch (Exception ex)
    {
        throw;
    }

    return dishes;
}

public List<Cuisine> GetCuisines(int restaurentID, string cousineID)
{
    List<Cuisine> cuisines = null;
    try
    {
        SqlCommand cmd = new SqlCommand("spGetCuisines", GetConnection());
        cmd.CommandType = System.Data.CommandType.StoredProcedure;
        cmd.Parameters.AddWithValue("RestaurantID", restaurentID);
        cmd.Parameters.AddWithValue("CuisineID", cousineID);
        SqlDataReader dreader = cmd.ExecuteReader();
        cuisines = new List<Cuisine>();
        while (dreader.Read())
        {
            cuisines.Add(new Cuisine()
            {
                CuisineID = (int)dreader["CuisineID"],
                CuisineName = (string)dreader["CuisineName"]
            });
        }
    }
    catch (Exception ex)
    {
        throw;
    }

    return cuisines;
}

public List<Dishes1> GetAllDishes()
{
    List<Dishes1> dishes = null;
    try
    {
        SqlCommand cmd = new SqlCommand("Select DishID, DishName From Dishes1", GetConnection());
        cmd.CommandType = System.Data.CommandType.Text;
        SqlDataReader dreader = cmd.ExecuteReader();
        dishes = new List<Dishes1>();
        while (dreader.Read())
        {
            dishes.Add(new Dishes1()
            {
                DishID = (int)dreader["DishID"],
                DishName = (string)dreader["DishName"]
            });
        }
    }
    catch (Exception ex)
    {
        throw;
    }

    return dishes;
}

public List<Cuisine> GetAllCuisine()
{
    List<Cuisine> cuisines = null;
    try
    {
        SqlCommand cmd = new SqlCommand("Select CuisineID,  CuisineName From Cuisine1", GetConnection());
        cmd.CommandType = System.Data.CommandType.Text;
        SqlDataReader dreader = cmd.ExecuteReader();
        cuisines = new List<Cuisine>();
        while (dreader.Read())
        {
            cuisines.Add(new Cuisine()
            {
                CuisineID = (int)dreader["CuisineID"],
                CuisineName = (string)dreader["CuisineName"]
            });
        }
    }
    catch (Exception ex)
    {
        throw;
    }

    return cuisines;
}

public List<Facilities1> GetAllFacilities()
{
    List<Facilities1> facilities = null;
    try
    {
        SqlCommand cmd = new SqlCommand("Select FacilityID, FacilityName from Facilities1", GetConnection());
        cmd.CommandType = System.Data.CommandType.Text;
        SqlDataReader dreader = cmd.ExecuteReader();
        facilities = new List<Facilities1>();
        while (dreader.Read())
        {
            facilities.Add(new Facilities1()
            {
                FacilityID = (int)dreader["FacilityID"],
                FacilityName = (string)dreader["FacilityName"]
            });
        }
    }
    catch (Exception ex)
    {
        throw;
    }

    return facilities;
}

} ///// ここに別のクラスがあります:

             public partial class Restaurant : System.Web.UI.Page
       {
public string facility = null;
public string cuis = null;
public string dish = null;
public string location = null;

protected void Page_Load(object sender, EventArgs e)
{
    if (!Page.IsPostBack)
    {
        BindListView();
        BindDishesAsCheckBoxes();
    }
}

private void BindListView()
{
    string searchText = this.txtSearch.Text;
    string facilityIDs = hfFacilityID.Value == "" ? "" : hfFacilityID.Value.Remove(hfFacilityID.Value.Length - 1);
    string dishIDs = hfDishID.Value == "" ? "" : hfDishID.Value.Remove(hfDishID.Value.Length - 1);
    string cuisineIDs = hfCuisineID.Value == "" ? "" : hfCuisineID.Value.Remove(hfCuisineID.Value.Length - 1);

    try
    {
        DBAccess objDB = new DBAccess();
        listView.DataSource = objDB.GetAllRestaurents(searchText, dishIDs, facilityIDs, cuisineIDs);
        listView.DataBind();
    }
    catch (Exception ex)
    {

    }
}

private void BindDishesAsCheckBoxes()
{
    try
    {
        DBAccess objdb = new DBAccess();

        //dishes
        chkDishes.DataSource = objdb.GetAllDishes();
        chkDishes.DataBind();

        //cuisines
        chkCuisine.DataSource = objdb.GetAllCuisine();
        chkCuisine.DataBind();

        //facilities
        chkFacilities.DataSource = objdb.GetAllFacilities();
        chkFacilities.DataBind();
    }
    catch (Exception ex)
    {

    }
}

#region itemdatabound

protected void ContactsListView_ItemDataBound(object sender, ListViewItemEventArgs e)
{

    string facilityIDs = hfFacilityID.Value == "" ? "" : hfFacilityID.Value.Remove(hfFacilityID.Value.Length - 1);
    string dishIDs = hfDishID.Value == "" ? "" : hfDishID.Value.Remove(hfDishID.Value.Length - 1);
    string cuisineIDs = hfCuisineID.Value == "" ? "" : hfCuisineID.Value.Remove(hfCuisineID.Value.Length - 1);
    try
    {
        if (e.Item.ItemType == ListViewItemType.DataItem)
        {
            Label lbl1 = (Label)e.Item.FindControl("lblRestaurentID");
            DBAccess objdb = new DBAccess();

            //bind  facility
            Repeater rpFacility = (Repeater)e.Item.FindControl("rptFacility");
            rpFacility.DataSource = objdb.GetFacilities(Convert.ToInt32(lbl1.Text), facilityIDs);
            rpFacility.DataBind();

            //bind  dishes
            Repeater rpDish = (Repeater)e.Item.FindControl("rptDish");
            rpDish.DataSource = objdb.GetDishes(Convert.ToInt32(lbl1.Text), dishIDs);
            rpDish.DataBind();

            //bind  dishes
            Repeater rptCuisine = (Repeater)e.Item.FindControl("rptCuisine");
            rptCuisine.DataSource = objdb.GetCuisines(Convert.ToInt32(lbl1.Text), cuisineIDs);
            rptCuisine.DataBind();
        }
    }
    catch (Exception ex)
    {
        //dvError.Visible = true;
        //lblErrorMessage.Text = ex.Message;
    }
}

#endregion

protected void chkDishes_SelectedIndexChanged(object sender, EventArgs e)
{
    foreach (ListItem item in chkDishes.Items)
    {
        if (item.Selected)
        {
            string id = item.Value;
            hfDishID.Value += id + ",";
            BindListView();
        }
    }
}

protected void chkCuisine_SelectedIndexChanged(object sender, EventArgs e)
{
    foreach (ListItem item in chkCuisine.Items)
    {
        if (item.Selected)
        {
            string id = item.Value;
            hfCuisineID.Value += id + ",";
            BindListView();
        }
    }
}

protected void chkFacilities_SelectedIndexChanged(object sender, EventArgs e)
{
    foreach (ListItem item in chkFacilities.Items)
    {
        if (item.Selected)
        {
            string id = item.Value;
            hfFacilityID.Value += id + ",";
            BindListView();
        }
    }
}

protected void btnSeach_Click(object sender, EventArgs e)
{
    BindListView();
}

}

4

2 に答える 2

0

ユーザーが文字列を正しく入力することに依存する動的 SQL を作成しています。文字列作成のエラーが原因で爆発が発生している可能性があると思います。

デバッグするには、次の行を変更します。

 Execute sp_executesql @sql

 print @sql

これにより、式の生のテキストが得られます。それをコピーして貼り付けて、何が爆破されているかを確認できます。文字列から構築しているエンジンに操作を転置しているという点で、動的SQLは非常に速く乱雑になる可能性があることに注意してください。

ユーザーが正当な変数を渡していることを確認する必要があります

' ''valA'', ''valB'', ''ValC'' '

varchar フィールド自体である varchar フィールドの配列を渡すときに、引用符を二重引用符でマークアップする必要があるためです。渡されるフィールド自体が正当であることを確認する必要があるため、これは問題を引き起こします。一部の人々は、この問題に対処するための別の手段を考え出したので、コードをデバッグする方法に加えて、いくつかの提案を提供できます。

正直なところ、SQL Server 2008以降を使用している場合は、「テーブルタイプ」を使用して、テーブルタイプにすることができるカスタムタイプを宣言することを検討します. 探している配列をそのテーブルに入力し、それを渡します。2008年以降のテーブル型を取るテーブル関数を構築できます。IMHO関数は常にprocsと同じように機能するとは限りませんが、非常に読みやすく、オブジェクトとして単独で機能しますリンクされているため、カプセル化と使いやすさのルールに従うのに非常に適しています。

于 2013-01-31T17:00:17.843 に答える
0

を動的に構築している理由は@sql、料理、料理、施設の基準として ID のカンマ区切りのリストを提供したいからだと思います。

ただし、これによりクエリが判読できなくなります。したがって、これを行わないでください。

使用状況に応じて、これらの基準ごとにテーブル値パラメーターを使用するか、文字列を分割する分割関数を使用します。

シンプルだが読みやすい分割関数:

ALTER FUNCTION [dbo].[fnStringSplit] (@list ntext)
         RETURNS @table TABLE (token varchar(4000) collate SQL_Latin1_General_CP1_CI_AS) 
AS
BEGIN
      DECLARE @pos       int,
              @textpos   int,
              @chunklen  smallint,
              @chunk     nvarchar(4000),
              @leftover  nvarchar(4000),
              @token     nvarchar(4000),
              @delimiter nchar(1)

      SET @delimiter = N','
      SET @textpos = 1
      SET @leftover = ''
      WHILE @textpos <= datalength(@list) / 2
      BEGIN
         SET @chunklen = 4000 - len(@leftover)
         SET @chunk = @leftover + substring(@list, @textpos, @chunklen)
         SET @textpos = @textpos + @chunklen

         SET @pos = charindex(@delimiter, @chunk)
         WHILE @pos > 0
         BEGIN
            SET @token = left(@chunk, @pos - 1)
            INSERT @table (token) VALUES(@token)
            SET @chunk = substring(@chunk, @pos + 1, len(@chunk))
            SET @pos = charindex(@delimiter, @chunk)
         END

         SET @leftover = @chunk
      END

      INSERT @table(token) VALUES (@leftover)
      RETURN
END

クエリを書き直したら、それを修正するのは簡単です。

于 2013-01-31T17:05:56.323 に答える