5

私はこのタイプの質問がSOで少なくとも十数回尋ねられたことを知っていますが、私はここで見つけることができた以前のすべての質問と回答を調べましたが、私が見つけたものは当てはまりません。ページで複数のFormViewオブジェクトを使用していますが、そのうちの1つを編集するオプションを追加したいと思います。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にアクセスする必要がありました)。関数にパラメーターを追加するために彼らが提案したものを適用しました。私が見つけたのは、ストアドプロシージャに、更新プロシージャに含まれていないselectプロシージャからの「ルックアップ」値がいくつかあることです。更新しようとしているテーブルにはテスターのIDしかありませんが、ユーザーは自分の名前も表示したいので、そのテーブルを参照しますが、FormViewでは、これらのフィールドは編集モード中は読み取り専用であるため、それを変更しようとしないでください。他のすべてのパラメータが並んでいます...それらのルックアップ値のみがオフになっています。trace

渡すパラメータの特定のリストを含めることで、それらのパラメータのみを使用すると思いましたが、それは正しくないようです。すでにパラメータを指定しているので困惑していますが、selectストアドプロシージャのパラメータで上書きされていることはどこにもわかりません。これらの読み取り専用の値を使用しないようにするには、どこに指示すればよいですか?

これらはユーザーが必要とするため、元のストアドプロシージャから削除したくありません。私がこれまでに思いついた回避策の1つは、それらをストアドプロシージャに追加してから、決して使用しないことです。私はこれがうまくいくとかなり確信していますが、それは問題を修正するのではなく、問題を隠蔽するだけです。


編集:リクエストごとに追加のコード

これは、パラメータを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
4

2 に答える 2

7

自分でこれを理解することになった。これは、VisualStudioがストアドプロシージャのスキーマに基づいてテンプレートを作成してくれたという事実に関連していました。テンプレートが自動生成されると、<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が、それを更新に含める必要がある場合(行IDなど)、今回はパラメーターが少なすぎるため、機能しません。<UpdateParameters>そこには何もついていないように見えるので、このセクションの目的は何なのか疑問に思っています...

于 2013-02-06T21:04:17.357 に答える
1

たとえば、OnDeletingイベント(e.Command.Parameters.RemoveAt(i))中に、不要なパラメータを削除できます。

于 2016-06-15T19:53:31.490 に答える