【问题标题】:MS Dynamics CRM trapping .NET error before I can handle itMS Dynamics CRM 在我处理之前捕获 .NET 错误
【发布时间】:2010-05-10 16:01:28
【问题描述】:

这很有趣。

我编写了一个自定义搜索页面,该页面提供了比默认联系人视图更快、对用户更友好的搜索,并且还允许同时搜索线索和联系人。它使用绑定到查询过滤视图的 SqlDataSources 的 GridViews。我相信有人会抱怨我没有为此使用网络服务,但这只是我们做出的设计决定。

这些 GridView 存在于 UpdatePanels 中,以便在搜索时启用非常流畅的 AJAX 更新。

一切都很好。几乎可以部署了,除了一件事:一些长时间运行的搜索正在触发无法捕获的 SQL 超时异常。

    [SqlException: Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.]
  at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)
  at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
  at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj)
  at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
  at System.Data.SqlClient.SqlDataReader.ConsumeMetaData()
  at System.Data.SqlClient.SqlDataReader.get_MetaData()
  at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
  at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async)
  at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result)
  at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
  at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)
  at System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior)
  at System.Data.Common.DbCommand.System.Data.IDbCommand.ExecuteReader(CommandBehavior behavior)
  at System.Data.Common.DbDataAdapter.FillInternal(DataSet dataset, DataTable[] datatables, Int32 startRecord, Int32 maxRecords, String srcTable, IDbCommand command, CommandBehavior behavior)
  at System.Data.Common.DbDataAdapter.Fill(DataSet dataSet, Int32 startRecord, Int32 maxRecords, String srcTable, IDbCommand command, CommandBehavior behavior)
  at System.Data.Common.DbDataAdapter.Fill(DataSet dataSet, String srcTable)
  at System.Web.UI.WebControls.SqlDataSourceView.ExecuteSelect(DataSourceSelectArguments arguments)
  at System.Web.UI.DataSourceView.Select(DataSourceSelectArguments arguments, DataSourceViewSelectCallback callback)
  at System.Web.UI.WebControls.DataBoundControl.PerformSelect()
  at System.Web.UI.WebControls.BaseDataBoundControl.DataBind()
  at System.Web.UI.WebControls.GridView.DataBind()
  at System.Web.UI.WebControls.BaseDataBoundControl.EnsureDataBound()
  at System.Web.UI.WebControls.CompositeDataBoundControl.CreateChildControls()
  at System.Web.UI.Control.EnsureChildControls()
  at System.Web.UI.Control.PreRenderRecursiveInternal()
  at System.Web.UI.Control.PreRenderRecursiveInternal()
  at System.Web.UI.Control.PreRenderRecursiveInternal()
  at System.Web.UI.Control.PreRenderRecursiveInternal()
  at System.Web.UI.Control.PreRenderRecursiveInternal()
  at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)

我发现 CRM 正在执行 server.transfer 来捕获此错误,因为当此错误发生时,我的 UpdatePanels 开始抛出 JavaSript 错误。我只能通过在 IE 中使用 JavaScript 调试器来获得完整的错误消息。

发现此错误后,我认为解决方案很简单。我只需要将我的数据绑定调用包装在 try/catch 块中以捕获任何错误。

不幸的是,CRM 的 IIS 配置似乎具有神奇的能力,可以在错误返回到我的代码之前捕获它。使用调试器我从来没有看到它。它永远不会到达我的 catch 块,但它显然发生在 SQL 数据源中,这显然是由我的 GridView 绑定触发的(通过堆栈跟踪)。

对此有什么想法吗?快把我逼疯了。

后面的代码(省略了一些不相关的功能):

  protected void Page_Load(object sender, EventArgs e)
  {
    //Initialize some stuff
    this.bannerOracle = new OdbcConnection(ConfigurationManager.ConnectionStrings["OracleConnectionString"].ConnectionString);

    //Prospect default
    HideProspects();
    HideProspectAddressColumn();

    //Contacts default
    HideContactAddressColumn();

    //Default error messages
    gvContacts.EmptyDataText = "Sad day. Your search returned no contacts.";
    gvProspects.EmptyDataText = "Sad day. Your search returned no prospects.";

    //New search
    try
    {
      SearchContact(null, -1);
    }
    catch
    {
      gvContacts.EmptyDataText = "Oops! An error occured. This may have been a timeout. Please try your search again.";
      gvContacts.DataSource = null;
      gvContacts.DataBind();
    }
  }
  protected void txtSearchString_TextChanged(object sender, EventArgs e)
  {
    if(!String.IsNullOrEmpty(txtSearchString.Text))
    {
      try
      {
        SearchContact(txtSearchString.Text, Convert.ToInt16(lstSearchType.SelectedValue));
      }
      catch
      {
        gvContacts.EmptyDataText = "Oops! An error occured. This may have been a timeout. Please try your search again."; 
        gvContacts.DataSource = null;
        gvContacts.DataBind();
      }

      if (chkProspects.Checked == true)
      {
        try
        {
          SearchProspect(txtSearchString.Text, Convert.ToInt16(lstSearchType.SelectedValue));
        }
        catch
        {
          gvProspects.EmptyDataText = "Oops! An error occured. This may have been a timeout. Please try your search again.";
          gvProspects.DataSource = null;
          gvProspects.DataBind();
        }
        finally
        {
          ShowProspects();
        }
      }
      else
      {
        HideProspects();
      }
    }
  }
  protected void SearchContact(string search, int type)
  {
    SqlCRM_Contact.ConnectionString = ConfigurationManager.ConnectionStrings["MSSQLConnectionString"].ConnectionString;
    gvContacts.DataSourceID = "SqlCRM_Contact";

    string strQuery = "";
    string baseQuery = @"SELECT filteredcontact.contactid,
                 filteredcontact.new_libertyid,
                 filteredcontact.fullname,
                 'none' AS line1,
                 filteredcontact.emailaddress1,
                 filteredcontact.telephone1,
                 filteredcontact.birthdateutc AS birthdate,
                 filteredcontact.gendercodename
              FROM filteredcontact "; 
    switch(type)
    {
      case LASTFIRST:
        strQuery = baseQuery + "WHERE fullname LIKE @value AND filteredcontact.statecode = 0";
        SqlCRM_Contact.SelectCommand = strQuery;
        SqlCRM_Contact.SelectParameters.Add("value", DbType.String, search.Trim() + "%");
        break;
      case LAST:
        strQuery = baseQuery + "WHERE lastname LIKE @value AND filteredcontact.statecode = 0";
        SqlCRM_Contact.SelectCommand = strQuery;
        SqlCRM_Contact.SelectParameters.Add("value", DbType.String, search.Trim() + "%");
        break;
      case FIRST:
        strQuery = baseQuery + "WHERE firstname LIKE @value AND filteredcontact.statecode = 0";
        SqlCRM_Contact.SelectCommand = strQuery;
        SqlCRM_Contact.SelectParameters.Add("value", DbType.String, search.Trim() + "%");
        break;
      case LIBERTYID:
        strQuery = baseQuery + "WHERE new_libertyid LIKE @value AND filteredcontact.statecode = 0";
        SqlCRM_Contact.SelectCommand = strQuery;
        SqlCRM_Contact.SelectParameters.Add("value", DbType.String, search.Trim() + "%");
        break;
      case EMAIL:
        strQuery = baseQuery + "WHERE emailaddress1 LIKE @value AND filteredcontact.statecode = 0";
        SqlCRM_Contact.SelectCommand = strQuery;
        SqlCRM_Contact.SelectParameters.Add("value", DbType.String, search.Trim() + "%");
        break;
      case TELEPHONE:
        strQuery = baseQuery + "WHERE telephone1 LIKE @value AND filteredcontact.statecode = 0";
        SqlCRM_Contact.SelectCommand = strQuery;
        SqlCRM_Contact.SelectParameters.Add("value", DbType.String, search.Trim() + "%");
        break;
      case BIRTHDAY:
        strQuery = baseQuery + "WHERE filteredcontact.birthdateutc BETWEEN @dateStart AND @dateEnd AND filteredcontact.statecode = 0";
        try
        {
          DateTime temp = DateTime.Parse(search);
          if (temp.Year < 1753 || temp.Year > 9999)
          {
            search = string.Empty;
          }
          else
          {
            search = temp.ToString("yyyy-MM-dd");
          }
        }
        catch
        {
          search = string.Empty;
        }
        SqlCRM_Contact.SelectCommand = strQuery;
        SqlCRM_Contact.SelectParameters.Add("dateStart", DbType.String, search.Trim() + " 00:00:00.000");
        SqlCRM_Contact.SelectParameters.Add("dateEnd", DbType.String, search.Trim() + " 23:59:59.999");
        break;
      case SSN:
        //Do something
        break;
      case ADDRESS:
        strQuery = @"SELECT contactid,
               new_libertyid,
               fullname,
               line1,
               emailaddress1,
               telephone1,
               birthdate,
               gendercodename 
               FROM (SELECT FC.contactid,
                     FC.new_libertyid,
                     FC.fullname,
                     FA.line1,
                     FC.emailaddress1,
                     FC.telephone1,
                     FC.birthdateutc AS birthdate,
                     FC.gendercodename,
                     ROW_NUMBER() OVER(PARTITION BY FC.contactid ORDER BY FC.contactid DESC) AS rn 
                    FROM filteredcontact FC 
                    INNER JOIN FilteredCustomerAddress FA
                    ON FC.contactid = FA.parentid
                    WHERE FA.line1 LIKE @value AND FA.addressnumber <> 1 AND FC.statecode = 0 ) AS RESULTS
               WHERE rn = 1";
        SqlCRM_Contact.SelectCommand = strQuery;
        SqlCRM_Contact.SelectParameters.Add("value", DbType.String, search.Trim() + "%");
        ShowContactAddressColumn();
        break;
      default:
        strQuery = @"SELECT TOP 500 filteredcontact.contactid,
                 filteredcontact.new_libertyid,
                 filteredcontact.fullname,
                 'none' AS line1,
                 filteredcontact.emailaddress1,
                 filteredcontact.telephone1,
                 filteredcontact.birthdateutc AS birthdate,
                 filteredcontact.gendercodename
              FROM filteredcontact 
              WHERE filteredcontact.statecode = 0";
        SqlCRM_Contact.SelectCommand = strQuery;
        break;
    }
    if (type != ADDRESS)
    {
      HideContactAddressColumn();
    }
    gvContacts.PageIndex = 0;
    //try
    //{
    //  SqlCRM_Contact.DataBind();
    //}
    //catch
    //{
    //  SqlCRM_Contact.DataBind();
    //}
    gvContacts.DataBind();
  }
  protected void SearchProspect(string search, int type)
  {
    SqlCRM_Prospect.ConnectionString = ConfigurationManager.ConnectionStrings["MSSQLConnectionString"].ConnectionString;
    gvProspects.DataSourceID = "SqlCRM_Prospect";

    string strQuery = "";
    string baseQuery = @"SELECT filteredlead.leadid,
                 filteredlead.fullname,
                 'none' AS address1_line1,
                 filteredlead.emailaddress1,
                 filteredlead.telephone1,
                 filteredlead.lu_dateofbirthutc AS lu_dateofbirth,
                 filteredlead.lu_gendername
              FROM filteredlead ";

    switch (type)
    {
      case LASTFIRST:
        strQuery = baseQuery + "WHERE fullname LIKE @value AND filteredlead.statecode = 0";
        SqlCRM_Prospect.SelectCommand = strQuery;
        SqlCRM_Prospect.SelectParameters.Add("value", DbType.String, search.Trim() + "%");
        break;
      case LAST:
        strQuery = baseQuery + "WHERE lastname LIKE @value AND filteredlead.statecode = 0";
        SqlCRM_Prospect.SelectCommand = strQuery;
        SqlCRM_Prospect.SelectParameters.Add("value", DbType.String, search.Trim() + "%");
        break;
      case FIRST:
        strQuery = baseQuery + "WHERE firstname LIKE @value AND filteredlead.statecode = 0";
        SqlCRM_Prospect.SelectCommand = strQuery;
        SqlCRM_Prospect.SelectParameters.Add("value", DbType.String, search.Trim() + "%");
        break;
      case LIBERTYID:
        strQuery = baseQuery + "WHERE new_libertyid LIKE @value AND filteredlead.statecode = 0";
        SqlCRM_Prospect.SelectCommand = strQuery;
        SqlCRM_Prospect.SelectParameters.Add("value", DbType.String, search.Trim() + "%");
        break;
      case EMAIL:
        strQuery = baseQuery + "WHERE emailaddress1 LIKE @value AND filteredlead.statecode = 0";
        SqlCRM_Prospect.SelectCommand = strQuery;
        SqlCRM_Prospect.SelectParameters.Add("value", DbType.String, search.Trim() + "%");
        break;
      case TELEPHONE:
        strQuery = baseQuery + "WHERE telephone1 LIKE @value AND filteredlead.statecode = 0";
        SqlCRM_Prospect.SelectCommand = strQuery;
        SqlCRM_Prospect.SelectParameters.Add("value", DbType.String, search.Trim() + "%");
        break;
      case BIRTHDAY:
        strQuery = baseQuery + "WHERE filteredlead.lu_dateofbirth BETWEEN @dateStart AND @dateEnd AND filteredlead.statecode = 0";
        try
        {
          DateTime temp = DateTime.Parse(search);
          if (temp.Year < 1753 || temp.Year > 9999)
          {
            search = string.Empty;
          }
          else
          {
            search = temp.ToString("yyyy-MM-dd");
          }
        }
        catch
        {
          search = string.Empty;
        }
        SqlCRM_Prospect.SelectCommand = strQuery;
        SqlCRM_Prospect.SelectParameters.Add("dateStart", DbType.String, search.Trim() + " 00:00:00.000");
        SqlCRM_Prospect.SelectParameters.Add("dateEnd", DbType.String, search.Trim() + " 23:59:59.999");
        break;
      case SSN:
        //Do nothing
        break;
      case ADDRESS:
        strQuery = @"SELECT filteredlead.leadid,
                 filteredlead.fullname,
                 filteredlead.address1_line1,
                 filteredlead.emailaddress1,
                 filteredlead.telephone1,
                 filteredlead.lu_dateofbirthutc AS lu_dateofbirth,
                 filteredlead.lu_gendername
              FROM filteredlead WHERE address1_line1 LIKE @value AND filteredlead.statecode = 0";
        SqlCRM_Prospect.SelectCommand = strQuery;
        SqlCRM_Prospect.SelectParameters.Add("value", DbType.String, search.Trim() + "%");
        ShowProspectAddressColumn();
        break;
      default:
        strQuery = @"SELECT TOP 500 filteredlead.leadid,
                 filteredlead.fullname,
                 'none' AS address1_line1
                 filteredlead.emailaddress1,
                 filteredlead.telephone1,
                 filteredlead.lu_dateofbirthutc AS lu_dateofbirth,
                 filteredlead.lu_gendername
              FROM filteredlead WHERE filteredlead.statecode = 0";
        SqlCRM_Prospect.SelectCommand = strQuery;
        break;
    }
    if (type != ADDRESS)
    {
      HideProspectAddressColumn();
    }
    gvProspects.PageIndex = 0;
    //try
    //{
    //  SqlCRM_Prospect.DataBind();
    //}
    //catch (Exception ex)
    //{
    //  SqlCRM_Prospect.DataBind();
    //}
    gvProspects.DataBind();
  }

【问题讨论】:

  • 哇。这保持了本周发布在问题中的无关代码数量的记录。很有可能有人会超越这一点,但今天,你是赢家。

标签: .net gridview dynamics-crm sqldatasource


【解决方案1】:

使用SqlDataSourceSelected 事件,并检查Exception 属性以查看是否发生异常。您也可以使用ExceptionHandled 属性来表明您已经处理了该事件。

附:请注意您发布的代码中有多少是我回答问题所必需的。

【讨论】:

  • 嗨,约翰,我会试试的。我发布了我所做的代码量,因为我确信有人会声称我没有正确使用 try/catch。对不起,如果它毁了你的一天:)
  • @clifgriffin:它并没有毁了我的一天——我忽略了它。如果需要代码来解决您的问题,那可能会毁了您的一天。
  • 约翰,谢谢你的帮助。我能够使用以下代码解决我的问题: protected void SqlCRM_Contact_Selected(object sender, SqlDataSourceStatusEventArgs e) { if (e.Exception != null) { ResetContactOnError(); e.ExceptionHandled = true;我还能够通过设置页面级错误处理程序来捕获错误,但是直到 Render() 之后才捕获它,因此它无法操纵用户在该过程中看到的内容。 protected override void OnError(EventArgs e) { //Do stuff } 再次感谢 Clif
【解决方案2】:

我不确定为什么你不能捕捉到异常,但我猜这是因为数据绑定魔法。但是,您至少可以增加超时时间:

http://blog.customereffective.com/blog/2008/07/increase-crm-sq.html

希望有帮助!

【讨论】:

    猜你喜欢
    • 2016-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-15
    • 2012-05-21
    • 1970-01-01
    • 2016-02-12
    • 1970-01-01
    相关资源
    最近更新 更多