У процедуры или функции 'xyz' указано слишком много аргументов

Я знаю, что этот тип вопроса задавался по крайней мере дюжину раз на SO, но я просмотрел все предыдущие вопросы и ответы, которые я мог найти здесь, и ни один из них не подходит. Я использую несколько объектов FormView на своей странице и теперь хочу добавить возможность редактирования одного из них. FormView заполняется SqlDataSource, связанным с хранимой процедурой, поэтому я создал хранимую процедуру для обновления записей и добавил ее в SqlDataSource, которая теперь выглядит так:

<asp:SqlDataSource ID="TestSqlDataSource" runat="server" 
                   SelectCommandType="StoredProcedure" 
                   ConnectionString="<%$ ConnectionStrings:development %>" 
                   SelectCommand="usp_GetNewTestDetails" 
                   UpdateCommand="usp_UpdateTest" 
                   UpdateCommandType="StoredProcedure" 
                   onupdating="TestSqlDataSource_Updating">
    <SelectParameters>
        <asp:SessionParameter SessionField="TestID" Name="TestID"/>
    </SelectParameters>
    <UpdateParameters>
        <asp:Parameter Name="testId" Type="Int32"/>
        <asp:Parameter Name="testerLicense" Type="Int32" />
        <asp:Parameter Name="premiseOwner" Type="String" />
        <asp:Parameter Name="premiseAddress" Type="String" />
        <asp:Parameter Name="premiseCity" Type="String" />
        <asp:Parameter Name="premiseState" Type="String" />
        <asp:Parameter Name="premiseZip" Type="String" />
        <asp:Parameter Name="protectionType" Type="String" />
        <asp:Parameter Name="testType" Type="String" />
        <asp:Parameter Name="repairs" Type="String" />
        <asp:Parameter Name="notes" Type="String" />
        <asp:Parameter Name="testDate" Type="DateTime" />
        <asp:Parameter Name="employerName" Type="String" />
        <asp:Parameter Name="employerAddress" Type="String" />
        <asp:Parameter Name="phoneNumber" Type="String" />
        <asp:Parameter Name="emailAddress" Type="String" />
        <asp:Parameter Name="dataEntryName" Type="String" />
        <asp:Parameter Name="dataEntryPhone" Type="String" />
        <asp:Parameter Name="signature" Type="String" />
        <asp:Parameter Name="entryDate" Type="DateTime" />
    </UpdateParameters>
</asp:SqlDataSource>

Когда я пытаюсь обновить запись, я получаю сообщение об ошибке, в котором говорится, что в моем запросе слишком много параметров. Я трижды проверил, что параметры в моем коде точно совпадают (имя, номер и даже порядок) с параметрами в моей хранимой процедуре.

Пытаясь найти ответы, я наткнулся на этот пост, в котором упоминался этот сайт (пришлось перейти на archive.org, так как оригинал не работает). Я применил то, что они предложили для добавления параметров в функцию trace. Я обнаружил, что в моей хранимой процедуре есть несколько значений «поиска» из процедуры выбора, которых нет в процедуре обновления. Таблица, которую я пытаюсь обновить, имеет только идентификатор тестировщика, но пользователи также хотели бы видеть свое имя, поэтому оно ссылается на эту таблицу, но в FormView эти поля доступны только для чтения в режиме редактирования, поэтому они могут не пытайтесь изменить его. Все остальные параметры совпадают... только эти значения поиска отключены.

Я думал, что, включив конкретный список параметров для передачи, он будет использовать только эти параметры, но это кажется неверным. Теперь я в тупике, потому что я уже указал параметры и нигде не вижу, чтобы они перезаписывались параметрами из хранимой процедуры выбора. Где мне сказать, чтобы он не использовал эти значения только для чтения?

Я не хочу удалять их из исходной хранимой процедуры, потому что они понадобятся пользователям. Единственный обходной путь, который я придумал до сих пор, — это добавить их в хранимую процедуру, а затем просто никогда их не использовать. Хотя я вполне уверен, что это сработает, это скорее просто сокрытие проблемы, чем ее устранение.


EDIT: Дополнительный код по запросу

Это метод, который выводит параметры в функцию trace:

protected void TestSqlDataSource_Updating(object sender, SqlDataSourceCommandEventArgs e)
{
    for (int i = 0; i < e.Command.Parameters.Count; i++)
    {
        Trace.Write(e.Command.Parameters[i].ParameterName);
        if (e.Command.Parameters[i].Value != null)
        {
            Trace.Write(e.Command.Parameters[i].Value.ToString());
        }
    }
}

Это хранимая процедура, используемая для обновления:

ALTER PROCEDURE [dbo].[usp_UpdateTest]
    @testId INT ,
    @testerLicense INT ,
    @premiseOwner VARCHAR(50) ,
    @premiseAddress VARCHAR(150) ,
    @premiseCity VARCHAR(50) ,
    @premiseState VARCHAR(2) ,
    @premiseZip VARCHAR(10) ,
    @protectionType VARCHAR(11) ,
    @testType VARCHAR(2) ,
    @repairs VARCHAR(200) ,
    @notes VARCHAR(300) ,
    @testDate DATETIME ,
    @employerName VARCHAR(50) ,
    @employerAddress VARCHAR(150) ,
    @phoneNumber VARCHAR(25) ,
    @emailAddress VARCHAR(60) ,
    @dataEntryName VARCHAR(50) ,
    @dataEntryPhone VARCHAR(25) ,
    @signature VARCHAR(50) ,
    @entryDate DATETIME
AS 
    BEGIN
        SET NOCOUNT ON;

        UPDATE  dbo.Tests
        SET     TesterLicense = @testerLicense ,
                PremiseOwner = @premiseOwner ,
                PremiseAddress = @premiseAddress ,
                PremiseCity = @premiseCity ,
                PremiseState = @premiseState ,
                PremiseZip = @premiseZip ,
                ProtectionType = @protectionType ,
                TestType = @testType ,
                Repairs = @repairs ,
                Notes = @notes ,
                TestDate = @testDate ,
                EmployerName = @employerName ,
                EmployerAddress = @employerAddress ,
                PhoneNumber = @phoneNumber ,
                EmailAddress = @emailAddress ,
                DataEntryName = @dataEntryName ,
                DataEntryPhone = @dataEntryPhone ,
                Signature = @signature ,
                EntryDate = @entryDate 
        WHERE TestID = @testId
    END

person techturtle    schedule 05.02.2013    source источник
comment
Вы проверили, есть ли какие-либо орфографические ошибки или ошибка преобразования типа данных?   -  person Ruchi    schedule 05.02.2013
comment
@RuchiRahulDoshi Да. Я скопировал оба набора параметров в Excel и сравнил их построчно. Это была самая распространенная проблема в этом слишком распространенном здесь вопросе, поэтому я очень тщательно следил за тем, чтобы они были точными. Используя trace для отображения всех передаваемых параметров, я могу точно сказать, что на самом деле передается слишком много аргументов, но я не знаю, как это отключить.   -  person techturtle    schedule 05.02.2013
comment
Не могли бы вы вставить сюда свои usp_UpdateTest и TestSqlDataSource_Updating, если вы не возражаете.   -  person Ruchi    schedule 05.02.2013
comment
@RuchiRahulDoshi Добавлен запрошенный код.   -  person techturtle    schedule 05.02.2013
comment
Я могу предложить вам одну вещь: для каждого параметра обновления в событии _updating укажите его один за другим, например, e.Command.Parameters[@testerLicense].Value = value -- поэтому, если есть проблема, связанная с тем, что он принимает больше параметров, он будет ограничено нет. указанных здесь параметров.   -  person Ruchi    schedule 06.02.2013
comment
Я вижу, что вы упомянули, что уже пробовали этот подход. Я ищу больше вариантов для исправления вашей проблемы. Обновите вас, если я найду что-то хорошее по этому поводу. Спасибо.   -  person Ruchi    schedule 06.02.2013


Ответы (2)


В итоге разобрался с этим самостоятельно. Это было связано с тем, что Visual Studio создала для меня шаблоны на основе схемы хранимой процедуры. Когда шаблоны генерируются автоматически, каждое текстовое поле в разделе <EditItemTemplate> создается следующим образом:

<asp:TextBox ID="TestIDTextBox" runat="server" Text='<%# Bind("TestID") %>'/>

Оказывается, это вызвано оператором Bind. VS автоматически создает параметр для любого поля, заполненного с помощью Bind. Хотя меня заставили поверить, что раздел <UpdateParameters> должен был переопределить это, на самом деле все было наоборот. Мне удалось запретить этим нескольким полям только для чтения передавать обратно свои параметры, изменив код этих полей с Bind на Eval:

<asp:TextBox ID="TestIDTextBox" runat="server" Text='<%# Eval("TestID") %>'/>

Теперь работает отлично.


Дополнение:

Обнаружено, что это вызывает ту же проблему и в другом направлении. Если вы пометите поле, которое не хотите редактировать, как Eval, но его необходимо включить в обновление (например, идентификатор строки), оно не будет работать, на этот раз для слишком малого количества параметров. Теперь мне интересно, какова цель раздела <UpdateParameters>, поскольку он, кажется, ничего там не следует...

person techturtle    schedule 06.02.2013
comment
Я попробовал ваше решение, заменив Bind на Eval. Это больше не дает мне ошибку «Процедура или функция« xyz »имеет слишком много аргументов», но данные не обновляются - person Thando Tee; 21.08.2013
comment
@ThandoTee Вы не хотите заменять все операторы Bind на Eval, а только те немногие, которые не должны обновлять данные. Eval — это команда только для чтения, поэтому она не будет обновлять эти поля. - person techturtle; 21.08.2013
comment
Спасибо за публикацию решения, которое вы придумали. Я не программист ASP, но это позволит мне помогать другим, когда SQL Server выдает ошибку. - person Jeff Moden; 26.05.2014

Вы можете удалить нежелательные параметры, например, во время события OnDeleting (e.Command.Parameters.RemoveAt(i)).

person aspsBestFriend    schedule 15.06.2016