【问题标题】:Logic edits all existing rows instead of adding new when using Save stored procedure使用保存存储过程时,逻辑编辑所有现有行而不是添加新行
【发布时间】:2021-08-24 13:49:14
【问题描述】:

我有一个关于 SQL 存储过程的问题。我已将我的 SQL Server 数据库连接到我的 ASP.NET Web 窗体应用程序,并创建了一个使用存储过程在数据库中保存数据的按钮。

我只想在前端使用两个字段,即 NameSurname。我不希望其他版主输入 Id(这是主键),因此存储过程必须在添加一些姓名和姓氏后自行递增。

但是,一旦将数据放入字段中,所有行都会填充该数据?

示例数据库。

Id Name Surname
1 Alex Smith
2 Bob Phoenix
3 Correy Lollas

点击插入按钮后,我创建了填充姓名和姓氏(ID 应该自动递增)

Id Name Surname
1 Test Name
2 Test Name
3 Test Name

存储过程,虽然我认为问题出在逻辑上。

ALTER  PROCEDURE [dbo].[spOrders_Save]

@Id int = NULL,
 @Name nvarchar(max),
 @Surname nvarchar(max),

AS
BEGIN
SET NOCOUNT ON;

 IF EXISTS (SELECT * FROM tblOrders WHERE ([Id] = @Id OR @Id IS NULL) )
    BEGIN 
        UPDATE tblOrders 
        SET 
        [Name] = @Name,
        [Surname] = @Surname ,
         WHERE ([Id] = @Id OR @Id IS NULL) 
    END 
    ELSE 
    BEGIN 
        INSERT INTO tblOrders 
        ( [Name],
         [Surname]
        )       VALUES 
        ( @Name,
         @Surname)
     END 
 END

逻辑

protected void FormView_Orders_DataBound(object sender, EventArgs e)                                               
{                                                                                                                       
 
    // If we have no rows, then change the formview into insert mode otherwise we are updating an existing row.         
    if (this.ORDERS_rowCount == 0)                                                                                 
    {                                                                                                                   
        FormView_Orders.ChangeMode(FormViewMode.Insert);                                                           
        for (int p = 1; p <= ORDERS_PAGE_COUNT; p++)                                                               
        {                                                                                                               
            (FormView_Orders.FindControl("btSaveData_" + p.ToString()) as Button).CommandName = "insert";          
        }                                                                                                               
    }                                                                                                                   
    else                                                                                                                
    {                                                                                                                   
        FormView_Orders.ChangeMode(FormViewMode.Edit);                                                             
        for (int p = 1; p <= ORDERS_PAGE_COUNT; p++)                                                               
        {                                                                                                               
            (FormView_Orders.FindControl("btSaveData_" + p.ToString()) as Button).CommandName = "update";          
        }                                                                                                                
    }                                                                                                                    
}          

我尝试解决的问题:

我尝试对 Id 进行硬编码,看看会发生什么。

令人惊讶的是,如果我运行localhost:1234/something.aspx?Id=4 然后输入详细信息,就会添加一个新行。所以我认为 C# 逻辑有问题?或者也许是存储过程?我知道前端没问题,因为它是自动化的。

Id Name Surname
1 Alex Smith
2 Bob Phoenix
3 Correy Lollas
4 Test Name

【问题讨论】:

  • 我对 T-SQL 不太感兴趣,但看起来 id 总是为空。你有 WHERE ([Id] = @Id OR @Id IS NULL)) 并且在开始时你将 id 设置为 null。我不确定 id 将如何/何时改变,所以总是更新?
  • 是的,似乎每次运行提交时,当我打开 SQL Server Profiler 时,无论其他值如何,@Id 始终为 NULL。
  • 所以我猜,搜索如何在 [your app-type] 的 sp 中设置 ID 的值。
  • 非常感谢!我找到了一种方法,只需从两个地方删除 is null 并开始增加。

标签: c# sql asp.net sql-server


【解决方案1】:

好的,正如您所说,您不想显示 ID。而且您不应该 = PK id 用于内部。

我认为在 SQL 中不需要存储过程。

如果行存在,内置的.net“适配器”可以处理,如果行不存在则可以处理。它会在这两种情况下自动为您添加或更新。

所以我真的没有看到问题。

所以,好吧,假设我们有这个包含 3 条记录的数据表:

好的,所以我们的标记是这样的:

     <div style="width:40%">

        <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="ID" 
            cssclass="table table-hover">
            <Columns>
                <asp:TemplateField HeaderText ="First Name">
                    <ItemTemplate>
                        <asp:TextBox ID="txtFirst" runat="server" Text = '<%# Eval("FirstName") %>'></asp:TextBox>
                    </ItemTemplate>
                </asp:TemplateField>

                <asp:TemplateField HeaderText ="Last Name">
                    <ItemTemplate>
                        <asp:TextBox ID="txtLast" runat="server" Text = '<%# Eval("LastName") %>'></asp:TextBox>
                    </ItemTemplate>
                </asp:TemplateField>

                <asp:TemplateField HeaderText ="City">
                    <ItemTemplate>
                        <asp:TextBox ID="txtCity" runat="server" Text = '<%# Eval("City") %>'></asp:TextBox>
                    </ItemTemplate>
                </asp:TemplateField>
            </Columns>
        </asp:GridView>
            <asp:Button ID="cmdSave" runat="server" Text="Save" CssClass="btn-primary" />

            <asp:Button ID="cmdAdd" runat="server" Text="Add Row" CssClass="btn-primary" style="margin-left:20px"/>
            <br />
     </div>

因此显示如下:

注意保存按钮。它像 word 或 Excel 一样工作。 你编辑了 - 然后点击保存。所以这就是过去 30 年 99% 的软件的运行方式!!!!

所以您可以点击添加行 - 将出现一个新行。您可以在该网格中使用标签 - 对您想要的任何行进行任何更改。我们不显示 ID。

如果您不点击保存,则不会添加和保存数据和行(同样 100% 的软件工作方式 - word、excel 等)

添加行、保存编辑和新行的代码如下所示:

    private DataTable rstPeople = new DataTable();

    protected void Page_Load(object sender, EventArgs e)
    {
    if (!IsPostBack)
    {
        LoadGrid();
        ViewState["MyTable"] = rstPeople;
    }
    else
        rstPeople = (DataTable)ViewState["MyTable"];

    }
    public void LoadGrid()
    {
        using (SqlCommand cmdSQL = new SqlCommand("SELECT * from People", 
                                    new SqlConnection(Properties.Settings.Default.TEST4)))
        {
            cmdSQL.Connection.Open();

            rstPeople.Load(cmdSQL.ExecuteReader());

            GridView1.DataSource = rstPeople;
            GridView1.DataBind();
        }
    }
    protected void cmdAdd_Click(object sender, EventArgs e)
    {

        // add a new row to the grid

        DataRow OneRow = rstPeople.Rows.Add();

        // OneRow("FirstName") = "Hello"  ' setup defaults for valuees 

        GridView1.DataSource = rstPeople;
        GridView1.DataBind();
    }

    protected void cmdSave_Click(object sender, EventArgs e)
    {

        // pull grid rows back to table.

        foreach (GridViewRow rRow in GridView1.Rows)
        {
            int RecordPtr = rRow.RowIndex;

            DataRow OneDataRow;

            OneDataRow = rstPeople.Rows[RecordPtr];
            OneDataRow["FirstName"] = ((TextBox)rRow.FindControl("txtFirst")).Text;
            OneDataRow["LastName"] = ((TextBox)rRow.FindControl("txtLast")).Text;
            OneDataRow["City"] = ((TextBox)rRow.FindControl("txtCity")).Text;
        }

        // now send table back to database with updates

        string strSQL = "SELECT ID, FirstName, LastName, City from People WHERE ID = 0";

        using (SqlCommand cmdSQL = new SqlCommand(strSQL, 
                                    new SqlConnection(Properties.Settings.Default.TEST4)))
        {
            cmdSQL.Connection.Open();
            SqlDataAdapter daupdate = new SqlDataAdapter(cmdSQL);
            SqlCommandBuilder cmdBuild = new SqlCommandBuilder(daupdate);

            daupdate.Update(rstPeople);
        }
    }

以上是:

代码不多——如果你写了太多代码——那么你做错了。

你不需要存储过程。

像 Word、Excel 和 99% 的软件一样?您只需编辑 - 然后点击保存,就完成了。没有复杂的用户界面,没有复杂的编辑。我的意思是,您也许可以放入一个撤消按钮(1 行代码 - 只需再次调用加载网格 - 真的很简单!!!)。

但是,如您所见,自动编号(身份)列全部由 .net 管理和完成 - 您不必担心。在上面,我们一次性将表发送回数据库。它不关心该表是否混合了编辑和新行。

我想我可能想添加一个删除按钮 - 除非给定行具有焦点,否则我可能不会显示该按钮。

但是,上面显示:

little markup
very clean - straight forward code - nothing fancy - no linq or anything.

【讨论】:

  • 这个很有见地。谢谢!
【解决方案2】:

答案是将@Id int = NULL 更改为@Id int 也只是WHERE ([Id] = @Id)。现在一切正常。

完整:

ALTER  PROCEDURE [dbo].[spOrders_Save]

@Id int,
 @Name nvarchar(max),
 @Surname nvarchar(max),

AS
BEGIN
SET NOCOUNT ON;

 IF EXISTS (SELECT * FROM tblOrders WHERE ([Id] = @Id)
    BEGIN 
        UPDATE tblOrders 
        SET 
        [Name] = @Name,
        [Surname] = @Surname ,
         WHERE ([Id] = @Id)
    END 
    ELSE 
    BEGIN 
        INSERT INTO tblOrders 
        ( [Name],
         [Surname]
        )       VALUES 
        ( @Name,
         @Surname)
     END 
 END

【讨论】:

  • 你没有改变它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-06-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-04
相关资源
最近更新 更多