从父表到子表的主键应用

时间:2014-01-13 03:18:43

标签: c# sql database sql-server-ce

我的SQL Server CE数据库中有以下表格:

ORDERS

OrderID (handled my DBMS)  
CustomerID  
OrderDate  

ORDER_DETAILS

OrderID (from the ORDERS table)  
ProductID  
OrderQTY  

我目前使用2个插入查询来向数据库添加新订单。第一个将订单插入ORDERS表并允许DBMS创建OrderID,第二个使用提供的OrderID插入ORDER_DETAILS表。

我在下面使用的方法看起来非常笨拙,并且可能容易受到并发问题的影响。当新记录插入OrderID表时,有没有办法让DBMS处理ORDER_DETAILS表的正确ORDERS的创建?

这是我用来运行插入查询的C#:

    public int InsertOrder(Order order)
    {
        DBConnection connection = DBConnection.getInstance();
        connection.conn.Open();
        using (SqlCeCommand query = new SqlCeCommand(OrderCommandList.cmdInsertOrderHeader, connection.conn))
        {
            query.Parameters.AddWithValue("@CustomerID", order.CustomerID);
            query.Parameters.AddWithValue("@OrderDate", order.OrderDate);
            query.ExecuteNonQuery();
        }

        //retrieves the PK for the recently inserted record
        int newOrderPK = 0;
         using(SqlCeCommand cmdGetIdentity = new SqlCeCommand("SELECT @@IDENTITY", connection.conn))
         {
             newOrderPK = Convert.ToInt32(cmdGetIdentity.ExecuteScalar());
         }
         connection.conn.Close();
        InsertOrderDetails(order, newOrderPK);
        return newOrderPK;
    }

    //inserts all the order details associated with the Order object
    private void InsertOrderDetails(Order order, int orderForeignKey)
    {
        foreach (OrderDetail od in order.OrderLineItems)
        {
            DBConnection connection = DBConnection.getInstance();
            connection.conn.Open();
            using (SqlCeCommand query = new SqlCeCommand(OrderCommandList.cmdInsertOrderDetails, connection.conn))
            {
                query.Parameters.AddWithValue("@OrderID", orderForeignKey);
                query.Parameters.AddWithValue("@ProductID", od.ProductID);
                query.Parameters.AddWithValue("@OrderQty", od.QtyOrdered);
                query.ExecuteNonQuery();
            }
            connection.conn.Close();
        }
    }

1 个答案:

答案 0 :(得分:0)

更改存储过程以选择生成的标识值,并使用SELECT SCOPE_IDENTITY();而不是SELECT @@IDENTITY;。实际上,最好是使用OUTPUT参数,但现在我假设您将继续使用SELECT。 e.g。

INSERT dbo.Orders(CustomerID,OrderDate) SELECT @CustomerID,@OrderDate;
SELECT ID = SCOPE_IDENTITY();

然后,对于插入而不是ExecuteNonQuery(),而不是SELECT @@IDENTITY的单独命令,您只需要一个ExecuteScalar来执行这两个命令。

使用TVP可以做得更好,您可以使用单个存储过程发送订单和所有详细信息行。然而,CE有点过时 - 不确定它是否支持TVP。您应该考虑使用Express / LocalDB。