我已经向三位程序员展示了这个问题,我们都很困惑。我在foreach循环中调用Sql Server存储过程,其结果始终与第一次调用相同。即使我硬编码参数(删除循环),也只有第一个结果分配给所有后续调用。

存储过程由Entity Framework函数导入(首先使用设计器的EF4数据库)调用。调用代码位于作为类库的存储库中。该存储库由一个单独的Asp.net Webforms项目调用。问题代码如下所示:

IEnumerable<WorkOrder> orders = _context.GetWorkOrders(UserName, workOrder, customerCode).ToList();

OrderStatus lastStatus = new OrderStatus();

foreach (Order order in orders)
{
     lastStatus = _context.GetOrderStatus(order.OrderNumber).FirstOrDefault();
     order.LastOrderStatus = lastStatus.OrderStatus;
}


如您所见,这是非常基本的东西。根据传入的订单号,我总是得到循环中第一个订单号的结果。我已经关闭了Ajax(我使用的Telerik控件的一部分),因为过去这对我造成了莫名其妙的错误。我真的希望您能提出一种调试此问题的方法!提前致谢。

编辑:Daniel J.G.的评论使我成为this possible solution。现在,我需要弄清楚如何应用Ladislav Mrnka的答案...“尝试使用MergeOption.OverwriteChanges直接调用ExecuteFunction。”

最佳答案

我正在回答自己的问题(因为几天后没有其他人回答)。该问题是由Entity Framework数据库的第一个设计器引起的。它生成的代码将缓存第一个存储过程的结果,从而导致后续调用中的不良结果。

正如我在对问题的编辑中提到的那样,此修复程序涉及替换ExecuteFunction使用的默认MergeOption参数。您需要使用MergeOption.OverwriteChanges而不是默认值(我相信它是MergeOption.PreserveChanges)。

您可以在生成的代码中更改该参数,但是每次重新构建设计器时所做的更改都会丢失。相反,我只是将生成的代码复制到我的存储库类,将MergeOption更改为OverwriteChanges,然后停止使用生成的代码。最终结果如下所示:

IEnumerable<WorkOrder> orders = _context.GetWorkOrders(UserName, workOrder, customerCode).ToList();

OrderStatus lastStatus = new OrderStatus();

foreach (Order order in orders)
{

    ObjectParameter workOrderParameter;
    if (wo.WorkOrder != null)
    {
        workOrderParameter = new ObjectParameter("WorkOrder", order.WorkOrder);
    }
    else
    {
       workOrderParameter = new ObjectParameter("WorkOrder", typeof(global::System.String));
    }

    lastStatus = _context.ExecuteFunction<OrderStatus>("GetOrderStatus", MergeOption.OverwriteChanges, workOrderParameter).FirstOrDefault();

    if (status != null)
    {
        order.LastOrderStatus = status.OrderStatus;
    }
}


我还看到有一种方法可以修改T4模板,以使生成的代码使用正确的MergeOption参数。我还没有尝试过。如果您有兴趣take a look here

10-04 11:39