客户端上的错误处理

本主题介绍您通常要如何处理错误,以及采取哪些特定步骤来处理在检索或修改客户端数据时出现的错误。使用 WCF RIA Services,可以通过为数据操作提供一个回调方法并在该回调方法中检查错误来处理错误。使用回调方法是必需的,因为对数据操作的调用是异步的,所以通过异步方式引发任何异常。默认情况下,将对域操作中的任何错误引发异常。RIA Services 为您提供了处理这些错误以及指定框架不引发异常的方法。

加载数据时的错误处理

从查询方法加载数据时,您可以处理错误或选择忽略错误。具体而言,您可以从下面的选项中进行选择:

  • 使用带有回调方法参数的 Load 方法。在该回调方法中,处理该错误,并调用 MarkErrorAsHandled 方法以指示不引发异常。

  • 使用带有名为 throwOnErrorboolean 参数的 Load 方法。调用 Load 方法时将 throwOnError 设置为 false,以指示您不希望对查询错误引发异常。

  • 使用 Load 方法,该方法不带有回调方法参数或 boolean 参数。运行查询时出现的任何错误将导致未处理的异常。

下面的示例演示如何从查询加载数据并指定一个回调方法来检查加载操作中的错误。

Private _customerContext As New CustomerDomainContext

Public Sub New()
    InitializeComponent()

    Dim loadOp = Me._customerContext.Load(Me._customerContext.GetCustomersQuery(), AddressOf OnLoadCompleted, Nothing)
    CustomerGrid.ItemsSource = loadOp.Entities
End Sub

Private Sub OnLoadCompleted(ByVal lo As LoadOperation(Of Customer))
    If (lo.HasError) Then
        MessageBox.Show(String.Format("Retrieving data failed: {0}", lo.Error.Message))
        lo.MarkErrorAsHandled()
    End If
End Sub
private CustomerDomainContext _customerContext = new CustomerDomainContext();

public MainPage()
{
    InitializeComponent();

    LoadOperation<Customer> loadOp = this._customerContext.Load(this._customerContext.GetCustomersQuery(), OnLoadCompleted, null);
    CustomerGrid.ItemsSource = loadOp.Entities;
}

private void OnLoadCompleted(LoadOperation<Customer> lo)
{
    if (lo.HasError)
    {
        MessageBox.Show(string.Format("Retrieving data failed: {0}", lo.Error.Message));
        lo.MarkErrorAsHandled();
    }
}

提交数据时的错误处理

提交数据时,您无法像在 Load 方法中那样选择关闭异常。提交数据时出现的任何错误都将导致异常。具体而言,您可以从下面的选项中进行选择:

  • 使用 SubmitChanges 方法并提供一个回调方法作为参数。在该回调方法中,处理该错误,并调用 MarkErrorAsHandled 方法以指示不引发异常。

  • 使用 SubmitChanges 方法。提交数据时出现的任何错误都将导致未处理的异常。

下面的示例演示如何使用具有回调方法的 SubmitChanges 方法来处理错误。

Private Sub SaveButton_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
    _customerContext.SubmitChanges(AddressOf OnSubmitCompleted, Nothing)
End Sub

Private Sub RejectButton_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
    _customerContext.RejectChanges()
    CheckChanges()
End Sub

Private Sub CustomerGrid_RowEditEnded(ByVal sender As System.Object, ByVal e As System.Windows.Controls.DataGridRowEditEndedEventArgs)
    CheckChanges()
End Sub

Private Sub CheckChanges()
    Dim changeSet = _customerContext.EntityContainer.GetChanges()
    ChangeText.Text = changeSet.ToString()

    Dim hasChanges = _customerContext.HasChanges
    SaveButton.IsEnabled = hasChanges
    RejectButton.IsEnabled = hasChanges
End Sub

Private Sub OnSubmitCompleted(ByVal so As SubmitOperation)
    If (so.HasError) Then
        MessageBox.Show(String.Format("Submit Failed: {0}", so.Error.Message))
        so.MarkErrorAsHandled()
    End If
    CheckChanges()
End Sub
private void SaveButton_Click(object sender, RoutedEventArgs e)
{
    _customerContext.SubmitChanges(OnSubmitCompleted, null);
}

private void RejectButton_Click(object sender, RoutedEventArgs e)
{
    _customerContext.RejectChanges();
    CheckChanges();
}

private void CustomerGrid_RowEditEnded(object sender, DataGridRowEditEndedEventArgs e)
{
    CheckChanges();
}

private void CheckChanges()
{
    EntityChangeSet changeSet = _customerContext.EntityContainer.GetChanges();
    ChangeText.Text = changeSet.ToString();

    bool hasChanges = _customerContext.HasChanges;
    SaveButton.IsEnabled = hasChanges;
    RejectButton.IsEnabled = hasChanges;
}

private void OnSubmitCompleted(SubmitOperation so)
{
    if (so.HasError)
    {
        MessageBox.Show(string.Format("Submit Failed: {0}", so.Error.Message));
        so.MarkErrorAsHandled();
    }
    CheckChanges();
}

Invoke 操作中的错误处理

调用某个操作时,您可以选择与提交数据时相同的选项。具体而言,您可以从下面的选项中进行选择:

  • 在调用 invoke 操作时包括一个回调方法。在该回调方法中,处理该错误,并调用 MarkErrorAsHandled 方法以指示不引发异常。

  • 在不包括回调方法的情况下调用 invoke 操作。调用该方法时出现的任何错误将导致未处理的异常。

下面的示例演示包括回调方法的 invoke 操作。

Dim invokeOp As InvokeOperation(Of Integer)
invokeOp = customerContext.GetLocalTemperature(selectedPostalCode, AddressOf OnInvokeCompleted, Nothing)

Private Sub OnInvokeCompleted(ByVal invOp As InvokeOperation(Of Integer))
  If (invOp.HasError) Then
    MessageBox.Show(String.Format("Method Failed: {0}", invOp.Error.Message))
    invOp.MarkErrorAsHandled()
  Else
    result = invOp.Value
  End If
End Sub
InvokeOperation<int> invokeOp = customerContext.GetLocalTemperature(selectedPostalCode, OnInvokeCompleted, null);

private void OnInvokeCompleted(InvokeOperation<int> invOp)
{
  if (invOp.HasError)
  {
    MessageBox.Show(string.Format("Method Failed: {0}", invOp.Error.Message));
    invOp.MarkErrorAsHandled();
  }
  else
  {
    result = invokeOp.Value;
  }
}

身份验证服务中的错误处理

使用 AuthenticationService 类,您可以在调用以下方法时提供回调方法:

在该回调方法中,您可以通过提供代码来处理身份验证服务中的错误。下面的示例演示如何从登录按钮的事件处理程序调用 Login 方法。包含一个回调方法来响应登录操作的结果。

Private Sub LoginButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
    Dim lp As LoginParameters = New LoginParameters(UserName.Text, Password.Password)
    WebContext.Current.Authentication.Login(lp, AddressOf Me.LoginOperation_Completed, Nothing)
    LoginButton.IsEnabled = False
    LoginResult.Text = ""
End Sub

Private Sub LoginOperation_Completed(ByVal lo As LoginOperation)
    If (lo.HasError) Then
        LoginResult.Text = lo.Error.Message
        LoginResult.Visibility = System.Windows.Visibility.Visible
        lo.MarkErrorAsHandled()
    ElseIf (lo.LoginSuccess = False) Then
        LoginResult.Text = "Login failed. Please check user name and password."
        LoginResult.Visibility = System.Windows.Visibility.Visible
    ElseIf (lo.LoginSuccess = True) Then
        SetControlVisibility(True)
    End If
    LoginButton.IsEnabled = True
End Sub
private void LoginButton_Click(object sender, RoutedEventArgs e)
{
    LoginParameters lp = new LoginParameters(UserName.Text, Password.Password);
    WebContext.Current.Authentication.Login(lp, this.LoginOperation_Completed, null);
    LoginButton.IsEnabled = false;
    LoginResult.Text = "";
}

private void LoginOperation_Completed(LoginOperation lo)
{
    if (lo.HasError)
    {
        LoginResult.Text = lo.Error.Message;
        LoginResult.Visibility = System.Windows.Visibility.Visible;
        lo.MarkErrorAsHandled();
    }
    else if (lo.LoginSuccess == false)
    {
        LoginResult.Text = "Login failed. Please check user name and password.";
        LoginResult.Visibility = System.Windows.Visibility.Visible;
    }
    else if (lo.LoginSuccess == true)
    {
        SetControlVisibility(true);
    }
    LoginButton.IsEnabled = true;
}