1

下午好,

我目前正在尝试在 winforms 应用程序中使用实体框架 DbContext/Code First。我的类PrintQueueItem映射到数据库内的视图,该视图仅返回PrintQueueItemPrintStatus等于“待定”。这通过 DataGridView 显示给最终用户,因此他们可以查看在一天结束时要批量打印的内容。用户可以添加PrintQueueItem的实例,这也显示在 DataGridView 中。

当我尝试取消设置为打印的项目时,我的问题出现了。我将PrintStatus设置为Canceled,然后运行 ​​ExecuteSqlCommand 来更新数据库。在此之后,我尝试重新加载信息,但该项目仍显示在 DataGridView 中。我不确定为什么在再次加载信息后获得计数(通过本地)时,它已减一。知道为什么会这样,因为我认为 BindingList 为数据绑定提供了 2 路同步,并且 UI 会随着数据的变化而更新?

PrintQueueItem(模型)

public class PrintQueueItem
{
    public PrintQueueItem()
    {
        this.PrintQueueID = Guid.NewGuid();
        this.PrintStatus = "Pending";
        this.DateAdded = DateTime.Now;
    }

    public Guid PrintQueueID { get; set; }
    public Guid DocumentID { get; set; }
    public string PrintStatus { get; set; }
    public DateTime DateAdded { get; set; }

    public virtual Documentation Document { get; set; }
}

初始绑定

this.printQueueBinding.DataSource = db.PrintQueue.Local.ToBindingList();
this.printQueueGridView.AutoGenerateColumns = false;
this.printQueueGridView.DataSource = printQueueBinding;

更新 PrintQueueItem 上的 PrintStatus 并重新加载

PrintQueueItem item = printQueueBinding.Current as PrintQueueItem;
if (item == null)
{
    throw new ArgumentNullException("Could not obtain instance of selected 'PrintQueueItem'");
}
item.PrintStatus = "Cancelled";
this.db.Database.ExecuteSqlCommand("exec usp_PrintQueue_Update {0}, {1}",item.PrintQueueID, item.PrintStatus);
this.db.PrintQueue.Load();

一些附加说明

我没有调用 ExecuteSqlCommand,而是尝试调用 SaveChanges,但遇到异常说明:

"Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded." 

我假设这是因为在更新时不再在视图中找到该项目。如果不是这种情况,请告诉我。

在应用程序中使用过滤视图而不是过滤的原因是因为 BindingList 没有实现 IBindingListView,而且我无法实现 BindingList.Filter 方法来过滤 DataGridView 中显示的数据。也欢迎对此提出任何建议。

谢谢您的帮助。

4

1 回答 1

0

喝了几杯啤酒,让我头脑中混乱的逻辑从今天早些时候清理出来;我开始思考实际发生了什么,然后突然想到,当我尝试调用 SaveChanges 时,发生了并发异常。

我没有注意到引发的异常类型,因此未能正确处理它。我已经将我的代码更新为以下内容,因此当发生 DbUpdateConcurrencyException(预期,因为视图不再包含记录)时,遇到问题的实体将从数据库中刷新:

        try
        {
            if (Program.YesNoQuestion(string.Format("Cancel print job for the selected document?", printQueueGridView.SelectedRows.Count)) != System.Windows.Forms.DialogResult.Yes)
            {
                return;
            }

            PrintQueueItem item = printQueueBinding.Current as PrintQueueItem;
            if (item == null)
            {
                throw new ArgumentNullException("Could not obtain an instance of 'PrintQueueItem'");
            }

            item.PrintStatus = "Cancelled";
            this.db.Database.ExecuteSqlCommand("exec usp_PrintQueue_Update {0}, {1}", item.PrintQueueID,
                                                                                           item.PrintStatus);
            //this.db.PrintQueue.Load();
            this.db.SaveChanges();
        }
        catch (DbUpdateConcurrencyException ex)
        {
            foreach (DbEntityEntry entry in ex.Entries)
            {
                entry.Reload();
            }
        }

请让我知道是否有更好的方法来解决这个问题,因为我总是对其他想法持开放态度,并且总是有兴趣以正确的方式做事。有一个美好的夜晚!

于 2012-12-20T02:33:12.140 回答