Выберите параметр запроса из C# в хранимой процедуре - PullRequest
0 голосов
/ 04 марта 2020

Как SQL Запрос к серверу выбрать из параметра? Я просто хочу упростить выбор столбца на основе моего C# кода. Является ли это возможным?

Вот моя хранимая процедура:

ALTER PROCEDURE [dbo].[GetMembersDetailGenerateChanceTop10000]
    @EventId nvarchar(255), 
    @PeriodId nvarchar(255), 
    @QueryParam nvarchar(1000)
AS
BEGIN
    SET NOCOUNT ON;

    SELECT DISTINCT TOP 10000 @QueryParam
    FROM ign..Chance_Generated cg
    INNER JOIN ign..Contact c ON cg.ContactID = c.ContactId
    LEFT JOIN ign..CustomerAddress ca ON ca.parentid = cg.contactid 
    LEFT JOIN ign..new_cardlevelconfig cl ON cl.new_cardlevelconfigid = c.new_cardlevel
    LEFT JOIN ign..new_country co ON co.new_countryid = c.new_country 
    LEFT JOIN ign..new_province po ON po.new_provinceId = c.new_Province
    LEFT JOIN ign..StringMap sm ON sm.AttributeValue = c.new_IDType
    LEFT JOIN ign..new_city cy ON cy.new_cityId = c.new_CityCounty
    LEFT JOIN ign..new_transactionheader th ON cg.New_Name COLLATE DATABASE_DEFAULT = th.new_name COLLATE DATABASE_DEFAULT
    WHERE cg.EventId = @EventId 
      AND (ca.AddressNumber = '1' OR ca.AddressNumber IS NULL) 
      AND (sm.AttributeName IS NULL OR sm.AttributeName = 'new_idtype') 
      AND cg.periodId = @PeriodId

QueryParam, EventId, PeriodId будет заполнено кодом C#.

Вот мой C# код:

private List<GenerateModel> getDataTopFromStoreProcedure(string EventId, string PeriodId)
{
    // query select parameter
    string QueryParam = @"cg.Chance_Number, th.new_name as [th name], dateadd(HOUR,7,th.createdon)  as [th createdon], 
                        c.new_Initial, c.FirstName, c.LastName";

    string ConnString = GenerateChance.Properties.Settings.Default["DB_ConnectionString"].ToString();

    using (SqlConnection conn = new SqlConnection(ConnString))
    {
        SqlCommand cmd = new SqlCommand();
        cmd.CommandText = GetMembersDetailGenerateChanceTop10000;
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.CommandTimeout = 0; //no limit

        cmd.Parameters.Clear();
        cmd.Parameters.Add(new SqlParameter("QueryParam", QueryParam));
        cmd.Parameters.Add(new SqlParameter("EventId", EventId));
        cmd.Parameters.Add(new SqlParameter("PeriodId", PeriodId));

        cmd.Connection = conn;

        if (conn.State == ConnectionState.Open)
            conn.Close();

        conn.Open();

        using (SqlDataReader reader = cmd.ExecuteReader())
        {
            while (reader.Read())
            {
                list.Add(new GenerateModel
                {
                    ChanceNumber = reader["Chance_Number"].ToString(), //System.IndexOutOfRangeException Error
                    Receipt = reader["th name"].ToString(),
                    Date = reader["th createdon"].ToString(),
                    Initial = reader["new_Initial"].ToString(),
                    FirstName = reader["FirstName"].ToString(),
                    LastName = reader["LastName"].ToString(),
                });
            }
            reader.Close();
        }
    }

    return list;
}

Я не понимаю, как реализовать его метод, потому что я хочу получить возврат всех результатов выбора в объектной модели, но я всегда получаю ошибка

System.IndexOutOfRangeException: Chance_Number.

Честно говоря, почему я использую параметр выбора запроса, потому что я хочу получить значение из checkedListBox1, которое уже было определено ранее используя этот код, получите значение checkedListBox1 для определения запроса на выборку.

string QueryParam = "cg.Chance_Number";//auto get chance_number as select mandatory

for (int i = 0; i < checkedListBox1.CheckedItems.Count; i++)
{
    QueryParam += ", " + ((clsItemList)checkedListBox1.CheckedItems[i]).Value;
}

1 Ответ

1 голос
/ 04 марта 2020

Вы должны использовать конструктор с правильной длиной для параметров, как указано ниже, чтобы избежать проблемы. Подробнее о SQLParameter

publi c SqlParameter (string parameterName, System.Data.SqlDbType dbType, int size);

cmd.Parameters.Add(new SqlParameter("QueryParam", SqlDbType.NVarChar,1000)).Value = QueryParam;

Вам нужно внести еще несколько изменений:

  • То, как вы это делаете определили процедуру неправильно. Вы должны определить процедуру как dynamici c sql, чтобы @queryparam был присоединен к запросу SELECT, как показано ниже:
DECLARE @selectStmt NVARCHAR(MAX) = ''
DECLARE @sqldefinition NVARCHAR(4000) = '@EventId nvarchar(255), @PeriodId nvarchar(255)'

SET @selectStmt += 'select distinct top 10000 ' + @QueryParam  +
'from ign..Chance_Generated cg
inner join ign..Contact c on cg.ContactID = c.ContactId
left join ign..CustomerAddress ca on ca.parentid = cg.contactid 
left join ign..new_cardlevelconfig cl on cl.new_cardlevelconfigid = c.new_cardlevel
left join ign..new_country co on co.new_countryid = c.new_country 
left join ign..new_province po on po.new_provinceId = c.new_Province
left join ign..StringMap sm on sm.AttributeValue = c.new_IDType
left join ign..new_city cy on cy.new_cityId = c.new_CityCounty
left join ign..new_transactionheader th on cg.New_Name COLLATE DATABASE_DEFAULT = th.new_name COLLATE DATABASE_DEFAULT
where cg.EventId= '''+ @EventId +''' and (ca.AddressNumber = ''1'' or ca.AddressNumber is null) and (sm.AttributeName is null or sm.AttributeName = ''new_idtype'') 
and cg.periodId = ''' + @PeriodId + ''';' 

EXEC @sp_executesql @selectStmt, @sqldefinition, @EventId , @PeriodId 
``

- Always refer the tables with proper schema in the query

ign.SchemaName.new_country ign.SchemaName. new_province


...