我偶然发现了一个我无法解决的奇怪问题。
我有两种不同形式的DataContexts。我以一种形式创建了两个“客户”实体(客户A和客户Z),并通过表单的上下文保存它们。然后我回到另一个表格,在那里我管理订单。在这种形式下,我可以创建订单并搜索客户(或他的地址)。
public void CustomerAddressSearched()
{
// Get all delivery addresses matching keyword
List<Address> addressList = customerModel.GetMatchingDeliveryAddresses(view.OrderSearchKeyword);
// If there is no matching address
if (addressList.Count == 0)
{
MessageBox.Show(Properties.Resources.SearchNoResult);
}
// If there is a single matching address
else if (addressList.Count == 1)
{
activeOrder.Address = addressList[0];
PopulateOrderAddressControls(addressList[0]);
activeOrderIsSaved = false;
}
// If there is more than one matching address, open search result view for user to pick address
else
{
using (var form = new CustomerSearchView(addressList))
{
if (form.ShowDialog() == DialogResult.OK)
{
CustomerViewObject selectedCustomer = (CustomerViewObject)form.selectedCustomer;
activeOrder.Address = addressList.Where(a => a.Id == selectedCustomer.AddressId).FirstOrDefault();
activeOrder.AddressId = selectedCustomer.AddressId;
PopulateOrderAddressControls(activeOrder.Address);
activeOrderIsSaved = false;
}
}
}
EnableOrDisableControls();
}
我搜索了客户,并获得了两位客户的清单。我回到客户表单并将客户A的名称更改为客户B,保存,然后又返回并再次搜索。不幸的是,我得到了客户A和Z,而不是客户B.检查了数据库,客户B就在其中。然后我选择客户A作为我创建的订单并保存。创建了一个新的,再次搜索,这次我得到了客户B而不是A.我不知何故需要使用“旧”版本一次,否则新版本不显示。如果这是有道理的。
所以我检查了
List<Address> addressList = customerModel.GetMatchingDeliveryAddresses(view.OrderSearchKeyword);
查看我检索最新客户数据的方式是否有问题。
public List<Address> GetMatchingDeliveryAddresses(string keyword)
{
List<Address> addressList = new List<Address>();
foreach (var c in context.Customers)
{
if (c.DateDeleted == null)
{
var result = c.Address.Where(a => (a.LastName.Contains(keyword) || a.Company.Contains(keyword)) && a.IsDeliveryAddress == true)
.OrderByDescending(a => a.DateEffective)
.FirstOrDefault();
if (result != null)
{
addressList.Add(result);
}
}
}
return addressList;
}
果然,在foreach循环中调试和停止时,我注意到最新版本(客户B)未加载(如果我没有使用它至少一次或重新启动程序/创建了新的上下文)。
我把
var list = context.Addresses.ToList();
在foreach循环之前,只是为了检查他是否根本不加载新的客户地址,但突然之间它起作用了,foreach循环加载了最新的客户版本。我再次删除了该行,它停止了工作。把它放回去,再次工作。我想我的问题是,为什么上面的那条线以某种方式刷新我的背景,或者发生了什么?
干杯!
我开始访问我有两个客户的客户目录(客户E和客户3)。我将它们重命名为客户ASD和客户666.返回订单并搜索客户。它运行以下代码:
public List<Address> GetMatchingDeliveryAddresses(string keyword)
{
List<Address> addressList = new List<Address>();
foreach (var c in context.Customers)
{
var result = c.Address.Where(a => (a.LastName.Contains(keyword) || a.Company.Contains(keyword)) && a.IsDeliveryAddress == true)
.OrderByDescending(a => a.DateEffective)
.FirstOrDefault();
System.Console.WriteLine("PRE Name: " + result.LastName);
}
var list = context.Addresses.ToList();
foreach (var c in context.Customers)
{
var result = c.Address.Where(a => (a.LastName.Contains(keyword) || a.Company.Contains(keyword)) && a.IsDeliveryAddress == true)
.OrderByDescending(a => a.DateEffective)
.FirstOrDefault();
System.Console.WriteLine("POST Name: " + result.LastName);
}
使用以下输出:
PRE Name: Customer E
PRE Name: Customer 3
POST Name: Customer ASD
POST Name: Customer 666
我不明白。
答案 0 :(得分:0)
问题是收到太多评论,所以我要在这里发布答案,因为我很确定这就是你有这个问题的原因。
根据您在评论中所写的内容:The context used to retrieve the customers is created when the form is initialized. I'm doing a context per form.
很明显您正在创建上下文以及表单本身(可能在构造函数中),这很多原因很多。有很多文章为什么你不应该这样做,但在这里我们正在讨论一个特定的问题,而且显然事实是你的上下文在你关闭表单之前不会改变。
现在是您的最后评论 - Turns out you were right, the code never made it to the dispose call for the customer directory context. But I still don't understand why it triggers such strange behaviour and how the line I added "fixed" it.
原因是DbContext
跟踪您在当前上下文处于活动状态之前所做的所有更改,但它只是一个表达式树(您可以根据需要查看表达式树)以及为了获得一些你需要执行某些调用的实际数据。其中一个是ToList()
,它强制执行更改,但引号在这里确实存在,因为它不是你应该怎么做的。
保持简短。如果您不打算使用任何类型的数据访问层,并且只是直接在表单中使用DbContext
,您应该从构造函数(或现在的位置)中删除上下文创建并创建新的上下文需要使用的时间(最可能是每种方法)。为了摆脱这个问题,你应该在using
语句中包含游览代码,如下所示:
public List<Address> GetMatchingDeliveryAddresses(string keyword)
{
using( var context = new MyEntitiesContext())
{
List<Address> addressList = new List<Address>();
foreach (var c in context.Customers)
{
var result = c.Address.Where(a => (a.LastName.Contains(keyword) || a.Company.Contains(keyword)) && a.IsDeliveryAddress == true)
.OrderByDescending(a => a.DateEffective)
.FirstOrDefault();
System.Console.WriteLine("PRE Name: " + result.LastName);
}
foreach (var c in context.Customers)
{
var result = c.Address.Where(a => (a.LastName.Contains(keyword) || a.Company.Contains(keyword)) && a.IsDeliveryAddress == true)
.OrderByDescending(a => a.DateEffective)
.FirstOrDefault();
System.Console.WriteLine("POST Name: " + result.LastName);
}
}
这应该是全部。