WPF绑定问题(更新时唯一约束冲突)如何拒绝更改?

WPF绑定问题(更新时唯一约束冲突)如何拒绝更改?,wpf,database,binding,constraints,Wpf,Database,Binding,Constraints,好的,请温柔一点,我是WPF和LINQ的新手-我这里有一个奇怪的问题。我有一个搜索屏幕和一个添加/编辑屏幕。我将添加/编辑屏幕绑定到“CompanyContact”对象,将搜索屏幕绑定到集合(CompanyContacts) 我在CompanyContact db表上有一个3列唯一约束(FirstName、LastName、CompanyId),因此同一个公司不能出现两次相同的名称 我还应该提到,我在CompanyContact表的“ModifiedDate”列上有一个“AFTER UPDATE

好的,请温柔一点,我是WPF和LINQ的新手-我这里有一个奇怪的问题。我有一个搜索屏幕和一个添加/编辑屏幕。我将添加/编辑屏幕绑定到“CompanyContact”对象,将搜索屏幕绑定到集合(CompanyContacts)

我在CompanyContact db表上有一个3列唯一约束(FirstName、LastName、CompanyId),因此同一个公司不能出现两次相同的名称

我还应该提到,我在CompanyContact表的“ModifiedDate”列上有一个“AFTER UPDATE”触发器,用于刷新ModifiedDate,因为我不喜欢让客户端PC指定ModifiedDate/时间。。。(我希望数据库跟踪记录的修改时间)。我让默认约束在插入时将GetDate()放入该列

假设在123公司有一个“史蒂夫·史密斯”,在123公司也有一个“史蒂夫·史密斯2”

如果我试图编辑一个现有的公司联系人(Steve Smith2@CompanyId=123),并将姓氏从“Smith2”更改为“Smith”,从而触发唯一约束(与Steve Smith@CompanyId=123冲突),那么一切似乎都正常(即,我这样做是为了编辑屏幕捕获SqlException,并通过重置base.DataContext将属性“重置”回其原始值,并通知用户-“嘿,你不能这样做……这会导致重复记录”)但是当我关闭编辑屏幕时(单击取消按钮)然后返回搜索屏幕,搜索结果中将显示有问题的数据…(即,现在有两条记录显示Steve Smith@CompanyId 123)

我尝试过很多事情,包括在尝试更新之前用LINQ编写代码来检查重复项……但似乎有一个比这更简单的解决方案?我非常相信将规则放入数据库,这样就可以对规则进行一致的强制执行,也就是说,对每个人(包括那些人)都执行相同的规则直接针对数据库(在后端)工作的人员

下面是添加/编辑屏幕的一个片段(搜索屏幕可以调用此函数)

这是“取消按钮”的代码

    private void btnCancel_Click(object sender, RoutedEventArgs e)
    {
        try
        {
            //HACK: this allows us to discard changes to the object passed in (when in EDIT mode)
            //TODO: research a truer WPF approach? (RoutedEvents?)
            _userCancelled = true;

            base.DataContext = _originalCompanyContact;

            this.Close();
        }
        finally
        {
        }
    }
以下是尝试在“添加/编辑”屏幕上保存时执行的代码:

try
{
  if (base.DataContext != null)
  {
   CompanyContactRepository ccr = new CompanyContactRepository();
   cc = ((CompanyContact)base.DataContext);
   ccr.Save(cc);
  }

  //dismiss the form after saving CompanyContact
  this.Close();
}
catch (SqlException sx)
{
  if (sx.Message.IndexOf("Violation of UNIQUE KEY constraint 'UN_CompanyContact_Value'.") == 0)
  {
    MessageBox.Show(String.Format("a CompanyContact with the name ({1} {0}) already exists for {2}", cc.FirstName, cc.LastName, cc.Company.Name), "Duplicate Record", MessageBoxButton.OK, MessageBoxImage.Exclamation);
  }
  else
  {
    //yes - catch and rethrow is probably a bad practice, but trying to ISOLATE UNIQUE constraint violation
    throw sx;
  }
}
finally
{
}
这里有一些用于保存的LINQ代码(抱歉,这太糟糕了!-我整天都在使用它)


好吧,我找到了一个解决方案,但它似乎更像是一个黑客而不是一个真正的解决方案……肯定有更好的方法来解决这个问题吗

我在LINQ代码(Save()函数中)中放置了一个catch块,如下所示:

if (sx.Message.IndexOf("Violation of UNIQUE KEY constraint 'UN_CompanyContact_Value'.") == 0)
  {
    //this will refresh the cache... so you won't see things that violate constraints
    //showing on the SearchCompanyContacts if you return from Edit CC screen...
    db.Refresh(RefreshMode.OverwriteCurrentValues, db.CompanyContacts);
    throw sx;
  }
  else
  {
    throw sx;
  }
这感觉非常空洞和不满意..我真的不喜欢捕获并重新引用异常的事实,但这是唯一能够详细解释保存失败原因的方法…如果我不需要执行db.Refresh()调用,则不需要这样做。。。(我可以让SqlException在调用堆栈中冒泡,我可以用ExceptionHandler类来处理这个问题)

我还更改了逻辑,这样如果用户取消,我会从编辑屏幕返回NULL,然后在搜索屏幕上,我也有这个小更改

selectedCompanyContact = editCompanyContact.EditCompanyContact(selectedCompanyContact.CompanyContactId);

if (selectedCompanyContact == null)
{
  //refresh from db..
  ExecuteSearch();
}
以便搜索屏幕刷新搜索结果,并显示“重置”值(即原始数据)

但这肯定不是编写LINQ的正确方法吗?我希望有某种设置可以定义,如果数据库拒绝它(违反了唯一约束、违反了外键等)然后扔掉集合中缓存的违反任何数据库规则的内容…现在有趣的是,搜索屏幕和编辑屏幕不会立即删除用户键入的内容,但一旦我按下“取消”按钮,屏幕将“刷新”,您将看到原始值

我喜欢此解决方案的一点是,如果您违反规则(您会收到“存在重复记录”消息),并且您仍然可以在绑定到实体“待保存”的字段中看到“未更改”的数据,这样您就可以查看数据并说“啊哈……我明白为什么拒绝此数据了”然后,您可以更改数据,“确定”按钮将继续拒绝坏数据,直到您的数据符合数据库中定义的所有规则,因此,如果需要,您可以单击“取消”按钮,然后它将放弃您的更改,搜索结果屏幕将刷新为“旧数据”

我对这个功能很感兴趣:

db.CompanyContacts.Context.GetChangeSet().Updates.Clear();
但不幸的是,它是一个只读列表,因此对它的调用失败了……但我想知道是否有办法使用列表中的对象(例如db.CompanyContacts.Context.GetChangeSet().Updates[0])将有问题的实体取出或分离/附加-不确定是否缺少某些内容,但感觉是这样的


我是认真的..不要叫我Shirley…;-)

ok发布了一些(蹩脚的)代码:)两个屏幕(编辑与搜索)是否使用相同的L2S上下文作为数据源?否-它们不使用相同的LINQ到SQL上下文。这听起来可能是个愚蠢的问题,但他们应该这样做吗?当谈到WPF时,我仍然是个新手,我发现它真的很令人困惑(我过去一直远离数据绑定,所以我一直在努力解决这个概念),这太令人沮丧了!!!我基本上希望datacontext拒绝缓存的更改。。。数据库已经“拒绝”了数据,但是LINQ“datacontext”仍然可以看到垃圾数据并显示出来。即使是编辑表单上表示当前数据的对象也会显示坏数据被拒绝,但是当我从编辑屏幕返回到搜索屏幕时,会显示垃圾数据。
selectedCompanyContact = editCompanyContact.EditCompanyContact(selectedCompanyContact.CompanyContactId);

if (selectedCompanyContact == null)
{
  //refresh from db..
  ExecuteSearch();
}
db.CompanyContacts.Context.GetChangeSet().Updates.Clear();