实体框架有时不会插入记录

时间:2015-11-12 19:41:50

标签: c# asp.net-mvc entity-framework-5 transactionscope

我对同事编写的代码有一个非常难看的问题。行动在TransactionScope之内。首先执行数据库插入:

var billingRecord = new Billing
                {
                    ACCOUNT_ID = AccountId,
                    AMOUNT = Amount,

                };
_ObjectContext.AddToBilling(billingRecord);
_ObjectContext.SaveChanges(SaveOptions.None)

然后执行Web服务调用:

var webServiceCallResult = Request(params);

if (webServiceCallResult.Result == 1)
{
    success = true;
}
else
{
    success = false;   
}

如果Web服务调用正常,则事务在finally块中完成:

finally
{
    if (success)
    {
        tran.Complete();
        _ObjectContext.AcceptAllChanges();
        _Logger.Info(String.Format("Transaction completed"));
    } 
    else
    {
        _Logger.Info(String.Format("Transaction uncompleted"));
    }
}

问题是由于某种原因,某些记录未存储在数据库中。我测试了很多交易但在开发环境中从未发生过,但有时会发生在生产环境中。当我说"有时"这是因为这种情况很不寻常或很少见。

查看日志文件,我可以看到消息:

  

交易完成

并且没有显示异常,因此Web服务调用良好且事务已完成但记录未插入表。

我知道创建TransactionScope没有必要,因为只有一个插入,不需要额外的数据库操作。 EF的对象上下文就像类中的全局var一样被创建并且永远不会丢弃,这是一种不好的做法,但据我所知,ObjectContext将被垃圾收集器销毁,所以我认为是不是导致问题的原因。

我阅读了很多关于事务和使用实体框架ObjectContext以及方法SaveChanges()AcceptAllChanges()的正确方法,甚至代码都没有使用应该运行的最佳实践。我不想只重构代码,我想知道问题的真正原因。

感谢您的帮助。

我正在使用:

  • ASP.NET MVC 3,
  • Entity Framework 5.0,
  • Ninject,
  • 的DevExpress

以下是完整的课程:

    public class Implementation : IExecute
    {
        private readonly Logger _Logger;
        private readonly ExampleEntities _ObjectContext = new ExampleEntities();

        public TopUpExecuteImplementation()
        {            
            _Logger = LogManager.GetLogger("Logger");
        }



        public Response perfomOperation(String account, String amount)
        {
            var success = false;

            using (var tran = new System.Transactions.TransactionScope())
            {
                try
                {
                    var accountRecord =
                        _ObjectContext.Accounts.First(
                            p => p.Account.Equals(account, StringComparison.InvariantCultureIgnoreCase));

                    var billingRecord = new Billing
                    {
                        ACCOUNT = account,
                        AMOUNT = amount,

                    };
                    _ObjectContext.AddToBillings(billingRecord);
                    _ObjectContext.SaveChanges(SaveOptions.None);

                    var webServiceCallResult = Request(account,amount);
                    _Logger.Info(String.Format("Request  Result {0} ", webServiceCallResult.Result));

                    if (webServiceCallResult.Result == 0)
                    {
                        success = false;
                    }
                    else
                    {
                        if ((String.IsNullOrEmpty(webServiceCallResult.statusCode) == false) &&
                            (webServiceCallResult.statusCode.Equals("Success",
                                StringComparison.InvariantCultureIgnoreCase)))
                        {
                            success = true;

                        }
                        else
                        {
                          success = false;

                        }
                    }
                }
                catch (OptimisticConcurrencyException ex)
                {
                    _Logger.Info(String.Format("Exception type {0} Exception {1} Inner Exception {2} ",
                        ex.GetType().ToString(), ex.Message,
                        ex.InnerException != null ? ex.InnerException.Message : String.Empty));
                    _ObjectContext.SaveChanges();
                    success = true;

                }
                catch (Exception e)
                {
                    _Logger.Info(String.Format("Exception type {0} Exception {1} Inner Exception {2} ",
                        e.GetType().ToString(), e.Message,
                        e.InnerException != null ? e.InnerException.Message : String.Empty));
                    success = false;
                }
                finally
                {
                    if (success)
                    {
                        tran.Complete();
                        _ObjectContext.AcceptAllChanges();
                        _Logger.Info(String.Format("Transaction completed"));
                    }
                    else
                        _Logger.Info(String.Format("Transaction uncompleted"));
                }
            }
            return returnValue;
        }
}

0 个答案:

没有答案