【问题标题】:Entity Framework Transactions in Foreach LoopForeach 循环中的实体框架事务
【发布时间】:2023-03-11 08:48:01
【问题描述】:

我正在尝试使用实体框架从 Windows 窗体 DataGridView 保存数据。由于某种原因,记录不保存到数据库中。我想循环遍历 DataGridView 并将每一行添加到一个 Transaction 对象中,并将所有事务(行)一次保存到数据库中。

我在交易中找到的信息来自MSDN。在寻找问题的解决方案时,我遇到了this SO post,它有一条评论,上面写着“我正在采取异常来捕获这样的异常。它会导致数据库操作静默失败。”这似乎是我的代码中发生的事情。我没有收到任何错误,它只是没有将任何内容保存到数据库中。

如何以原子方式保存所有事务并在出现故障时回滚?如何重新组织事物以正确捕获错误?如果注释正确,MSDN 中的代码有什么问题?

这是我的代码:

// Store the valid transactions
using ( var dbContextTransaction = context.Database.BeginTransaction() )
{
    try
    {
        Transaction oTransaction = new Transaction();

        foreach ( DataGridViewRow row in dgvInventoryTransactions.Rows )
        {
            if ( !row.IsNewRow )
            {
                // Get the product
                int iSelectedProduct = int.Parse( row.Cells[0].Value.ToString() );
                oTransaction.Product = context.Products.First( p => p.ID == iSelectedProduct );

                // Quantities
                oTransaction.FullQuantity = int.Parse( row.Cells[1].Value.ToString() );
                oTransaction.PartialQuantity = int.Parse( row.Cells[2].Value.ToString() );
                oTransaction.CalculatedQuantity = (double)oTransaction.FullQuantity + ( (double)oTransaction.PartialQuantity / (double)oTransaction.Product.Pieces );

                // Check to see if a truck has been selected
                if ( !string.IsNullOrEmpty( row.Cells[3].FormattedValue as String ) )
                {
                    // A truck has been selected
                    int iSelectedVehicle;
                    if ( int.TryParse( row.Cells[3].FormattedValue.ToString(), out iSelectedVehicle ) )
                    {
                        oTransaction.Vehicle = context.Vehicles.Where( v => v.VehicleNumber == iSelectedVehicle ).First();
                    }

                }

                // Check to see if the "Source" field contains data
                if ( !string.IsNullOrEmpty( row.Cells[4].FormattedValue as String ) )
                {
                    oTransaction.SourceNumber = row.Cells[4].Value.ToString();
                }

                // Check to see if the comments field contains data
                if ( !string.IsNullOrEmpty( row.Cells[5].FormattedValue as String ) )
                {
                    oTransaction.Comments = row.Cells[5].Value.ToString();
                }

                // Get the transaction type
                int value = int.Parse( cmboTransactionType.SelectedValue.ToString() );
                oTransaction.TransactionType = context.TransactionTypes.Where( t => t.ID == value ).First();

                // Get the current user
                var user = context.Employees.First( u => u.ID == Globals.User ); // One lookup...
                oTransaction.CreatedBy = user;
                oTransaction.LastUpdatedBy = user;                                     

                // Add the dates
                oTransaction.TransactionDate = dtpTransactionDate.Value;
                oTransaction.CreateDate = DateTime.Now;
                oTransaction.LastUpdatedDate = DateTime.Now;

                // Save the transaction
                context.SaveChanges();


            }

        }

        // Commit the changes to the database
        dbContextTransaction.Commit();

    }
    catch ( Exception )
    {
        dbContextTransaction.Rollback();
        MessageBox.Show( "Records were NOT saved successfully.", "Save Unsuccessful", MessageBoxButtons.OK, MessageBoxIcon.Information );
    }

}

【问题讨论】:

    标签: c# .net transactions entity-framework-6


    【解决方案1】:

    您尚未插入oTransaction 或将其连接到某个现有对象。 EF 不知道该对象存在。尝试AddObject 方法添加事务。这会将其注册到 EF。

    另外,您可以删除Rollback 调用。当没有提交时它会回滚。同时将消息框移出 using 块以快速结束事务。

    【讨论】:

    • 谢谢@usr!有效!如果事务在提交失败时回滚,回滚方法的目的是什么?
    • 我认为您可以使用它来强制提前回滚。它几乎不应该被调用。不知道为什么人们总是叫它!当您不调用 commit 并退出 using 块时,您认为会发生什么?我很好奇。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多