解BUG心得分享

不常见报错

一、调用HiddenApi报错

There is no active transaction. This error is usually caused by custom plug-ins that ignore errors from service calls and continue processing.

汉译:

没有活动事务。此错误通常由忽略服务调用错误并继续处理的自定义插件引起。

  • 简单方式是“重新生成”,看是否编译通过。一般是有语法错误,导致插件并没有上传成功。

  • 其他原因:可以去掉try……catch,使其显示更清晰的报错信息。

二、数组null.Length报错

自定义页面中:

Cannot read properties of undefined (reading ‘length’)

解决方案:

下面是我的处理这种模糊问题的处理思路。(注释排除法)

一、排除 js 内的 所有的xxx.length 的 变量是否是数组类型。
二、排除 html 代码上是否引用过xxx.length 。

如果以上注释了排除还是报错的话。

还需要关注的就是 v-for ,因为代码再执行到 v-for="(item,index) in arry" 这里时,如果arry不是个数组就会导致报错 xxxx.length 找不到,因为渲染的时候会内部运行 for 循环就会用到 xxx.length。这个是不能很快直观的能处理到的隐藏问题。

三、element CheckboxGroup组件没有v-model的时候也会报错。

问题重现:

<el-table-column
                 prop="new_commerceforms.Name"
                 label="贸易方式"
                 sortable
                 align="center"
                 width="130"
                 >
  <template slot-scope="scope">
    <el-select
               v-if="scope.row.isEdit"
               v-model="scope.row.new_commerceforms.Value"
               @change="new_commerceformsOnchange"
               placeholder="请选择"
               >
      <el-option
                 v-for="(item,index) in scope.row.new_commerceforms.**Options**"
                 :key="index"
                 :label="item.Name"
                 :value="item.Value"
                 >
      </el-option>
    </el-select>
    <span v-if="!scope.row.isEdit">{{
      scope.row.new_commerceforms.Name
      }}</span>
  </template>
</el-table-column>

后台写法必须是:PicklistModel写法

三、向数据库插入数据,主键重复报错

System.Exception: 违反了 PRIMARY KEY 约束“PK_new_deliverycarBase”。不能在对象“dbo.new_deliverycarBase”中插入重复键。重复键值为 (5daf6081-2dad-4e08-88b7-0c26a462f1b4)。

解法一:

foreach (var e in ec.Entities)
{
    ………………
        table.Rows.Clear();
    foreach (var car in carec.Entities)
    {
        ………………
            table.Rows.Add(row1);
    }
    this.Broker.BatchInsert("new_deliverycarBase", table);
}

说明:在foreach第二次插入数据之前,需要把上一次的 Rows 数据清空,否侧会造成主键重复。

解法二: 正解

foreach (var e in ec.Entities)
{
    ………………   
        foreach (var car in carec.Entities)
        {
            ………………
                table.Rows.Add(row1);
        }
}
this.Broker.BatchInsert("new_deliverycarBase", table);

说明: 累加处理完所有的Rows数据后,在循环的外面插入数据,就不会造成主键重复了。

未能加载文件或程序集

  • 尝试一:该报错出现在Controller调用的方法中,一般可以尝试去掉Command方法中的try{}catch(){}

  • 尝试二:如果是出现在Command方法中,在某一个调用接口的方法处抛出错误,最大可能是,接口不通导致

  • 正解:Json版本不匹配,或者crm.common版本不匹配等;升级版本或降级。

使用SQL查数据需配置DbDriver

报错1:ConnectionString can not be NULL

报错2:get DbSourceConfigItem error

解决办法:

  1. 查找XML的config文件:RekTec.XStudio.Data.DbSourceConfig.xml.config

  2. 添加/修改ConnectionString标签

  3. 查看标签DbSource里面的值是否与DbSourceConfigItem标签里面的Name属性值对应

案例:

<?xml version="1.0" encoding="utf-8"?>
<DbSourceConfig xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <DbSource>**portal**</DbSource>
  <ItemList>
    <!--Portal 数据库连接字符串-->
    <DbSourceConfigItem>
      <Name>**portal**</Name>
      <DriverType>sqlserver</DriverType>
      <ConnectionString>**Password=YTp@ssw0rd;User ID=sa;Initial Catalog=ytcrmdev_MSCRM;Data Source=10.66.227.81**</ConnectionString>
      <CommandTimeOut>60</CommandTimeOut>
      <ConnectionTimeOut>30</ConnectionTimeOut>
    </DbSourceConfigItem>
  </ItemList>
</DbSourceConfig>

实例对象位置放错,导致产生重复性数据

数据查出来是两条以上,但接收的值虽然也是两条,但一直都是返回结果的最后一条,且两条数据一模一样 原因在于:在new一个model对象的时候,没有在循环里面,而是放在了外面,从而引发了数据异常。

目标数据:

YT023210903    1  3000.00
YT21096210858  1  900.00

而实际接收到的数据:为重复数据

还可以尝试用去重方法取实验,如果不起作用就可以说明这个问题。

[{
  "new_customsinvoiceno": "YT21096210858",
  "Tradingway": 1,
  "Price": 900.0000,
  "new_parentname": "new_customsclearance",
  "new_entityId": "750D68F1-9A0B-EC11-A140-005056A4763A"
}, {
  "new_customsinvoiceno": "YT21096210858",
  "Tradingway": 1,
  "Price": 900.0000,
  "new_parentname": "new_customsclearance",
  "new_entityId": "750D68F1-9A0B-EC11-A140-005056A4763A"
}]

解决方案:

foreach (var item in vehicleGroup)
{
    FileAttachmentModel file = new FileAttachmentModel();  //必须放在循环内部,放在外部每循环一遍相当于替换一遍
    file.new_customsinvoiceno = item.new_customsinvoiceno;
    file.Tradingway = item.new_tradingway;
    file.Price = Math.Round(item.Price, 2);
    file.new_parentname = entityName;
    file.new_entityId = entityId;
    invoicenoList.Add(item.new_customsinvoiceno);
    fileAttachmentModels.Add(file);
}

总结:

  • 大多数情况下,实例化对象都必须放在循环里面。

Vue时间组件选择时间为UTC时间

如这种格式:2021/11/29T16:00:00 或者:11/29/2021 16:00:00

后端时间需要取本地时间,加8小时即可。

DateTime time = new DateTime();
bool a = DateTime.TryParse(model.new_plantime, out time);
if (a)
{
    shipplan["new_plantime"] = time.ToLocalTime();
}

Log.DebugMsg("传入参数时间:" + model.new_plantime);
Log.DebugMsg("输出参数时间:" + time.ToString("yyyy-MM-dd hh:mm:ss"));
Log.DebugMsg("处理后时间ToUniversalTime:" + time.ToUniversalTime().ToLocalTime().ToString("yyyy-MM-dd hh:mm:ss"));
Log.DebugMsg("处理后时间ToLocalTime:" + time.ToLocalTime().ToString("yyyy-MM-dd hh:mm:ss"));

传入参数时间:11/29/2021 16:00:00
输出参数时间:2021-11-29 04:00:00
处理后时间ToUniversalTime:2021-11-29 04:00:00
处理后时间ToLocalTime:2021-11-30 12:00:00

SQL查CRM的时间字段少8小时

处理办法如下:

DATEADD(HH,8,new_time)  --加8小时
CONVERT(varchar(12), DATEADD(HH, 8, new_date), 111 )   --去掉时分秒  2021/01/12
CONVERT(varchar(10), dateadd(HH, 8, dc.new_shipmentdate), 120)    --2021-01-12

--new_time为时间字段,涉及到海外,上面的方法不能用了
--UTC时间转本地时间:
DATEADD(hour, DATEDIFF(hour,GETUTCDATE(),GETDATE()), new_time)   --加8h
--本地时间转UTC时间:
DATEADD(hour, DATEDIFF(hour,GETDATE(),GETUTCDATE()), new_time)

操作流程中输入参数未添加报错

2021-11-07T13:26:28.846 plugin Error 值不能为 null。
参数名: value

程序在此处报错

NotificationFilterModel result = JsonConvert.DeserializeObject<NotificationFilterModel>(Content.Get(ExecutionContext));

使用RibbonBox时

使用Ribbonbox自定义工具时无法加载解决方案

报错信息如下:

解决方案[ZGJ_ _sIn_ flowtool]的ribbon创建失败: Error: 方法"DynamicClass.lambda method(System.Runtime.CompilerServices.Closure)"尝试访问方法"Microsof.Xrm.Sdk.Client.OrganizationServiceContext.CreateSequentialGuid0”失败。

解决办法:

选择实体的时候,把【✓】全部去掉,最后选择【否】即可。

切忌删除某些东西以保留一个目标实体,虽然看起来行,但其实不可行。

邮件提醒在消息中无法显示

可能原因如下:

  • 代码没有报错的前提下

    • 由于默认标题字符串长度为100,内容字符串长度为1000,明细中也同样如此; 当超出字符串最大限制的时候,则消息就无法显示,需手动调整长度。 在服务器中的log文件夹查看时,会出现以下报错信息:
2021-12-06 16:00:00.008 执行jobdc8e7461-0954-ec11-a13e-005056a43d65
2021-12-06 16:00:22.566 A validation error occurred.  The length of the 'new_content' attribute of the 'new_notification' entity exceeded the maximum allowed length of '1000'.

邮件发送两遍处理方法:

  • 方法一:登录服务器,重启异步服务;

  • 方法二: 修改插件异步改为同步;

    • 消息提醒默认为异步执行,可以尝试将异步改为同步,如果不行就可能是服务器异步执行有问题 插件注册步骤位置: (Assembly)RekTec.Crm.Plugin.Notification | (Plugin)RekTec.Crm.Plugin.Notification.new_remind_task_monitor | (Step)RekTec.Crm.Plugin.Remind(QGWJBGTJ_001):To Update new_liquidationattchange 默认: Asynchronous(异步) Server 改为: Synchronous(同步) Server

代码执行速度过慢问题:

自定义自动编号代码执行速度过慢问题

优化方案:

将**组织服务**的查询、更新数据库形式,改为**SQL**执行,速度将提升数倍不止。

解释:

组织服务处理数据库时,同时也会涉及到【权限】的控制,以及还会【触发Plugin】等,使得在循环遍历更新数据库时,

会严重拖慢程序的执行效率,因此不建议使用组织服务。

因为字段值带有空格问题。

因为导入数据的时候字段值带有空格而查询不到数据。

如果是后台代码处理数据,可以考虑加上去除前后空格方法Trim()

单据停用时报错

签核处理及签核处理步骤停用—代码控制出现的报错

情景一:正常理解及操作,直接更改为停用

代码示例

Entity crf=new Entity("new_flowapprovalcrf", crfid);
crf["statecode"]=1;
OrganizationService.Update(crf);

删除时报错提示

大致意思:此状态码在指定状态码中无效。

推断:写法不对,根据后面结论发现:状态描述字段也需要赋值

情景二:更改停用正确方法,常用,但可能并不通用

代码示例

SetStateRequest stepRequest = new SetStateRequest()
{
    EntityMoniker = new EntityReference("new_flowapprovalcrf", crfid),
    State = new OptionSetValue(1),//可用=0,停用=1
    Status = new OptionSetValue(2),  
    //(状态描述)可用=1,停用=2
};
OrganizationServiceAdmin.Execute(stepRequest);

未注意到列表值报错:

大致意思:2不是实体(new_flowapprovalcrf)中有效状态码。

推断:可能不存在。

情景三:获取到了列表值,但与状态不匹配报错

代码示例

SetStateRequest crfRequest = new SetStateRequest()
{
    EntityMoniker = new EntityReference("new_flowapprovalcrf", crfid),
    State = new OptionSetValue(1),//Active=0,Inactive=1
    Status = new OptionSetValue(5), //正确的是:把5改为6或7
    //(Active)待签核=4,已签核=5; (Inactive)待签核==6,已签核=7
};
OrganizationServiceAdmin.Execute(crfRequest);

列表值与状态不匹配报错:

大致意思:5不是Inactive状态代码中的有效状态码

推断:可能不匹配。

注册插件时报错常见解决思路

  • 是否接入了客户那边的VPN。

  • 是否发生了重命名操作,是的话,需要手动取消原有已注册的插件(只取消发生重命名的文件即可),然后重新注册即可。

不间断空格

读取xml文件时,名称不能以“ ”字符(十六进制值 0x20)开头

//正确格式
<attribute name='new_money' alias='AMOUNT' aggregate='sum' />
//含特殊空格,错误格式
<attribute name="new_money" alias="money" aggregate="sum"/>

解决方法:

NotePad++ 调成XML格式,通过观察颜色来判断。  删除它们中间的特殊空格即可。
  • 正确

  • 错误:

不间断空格

NBSP:“**Non-Breaking Space**” ,不间断空格

也称为: no-break space,non-breakable space (NBSP), hard space(硬空格), or fixed space

在HTML中,被编码为 或 &#160,宽度和普通空格一致。

在 Unicode 码点为 U+00A0 , 命名为Narrow No-Break Space

在 js 中是 \xA0

NBSP 是常用的编程和网页创建的行,不打破空间上的程序或文档的空间。

特性

  1. 禁止自动换行
  2. 禁止合并空白字符

在SGML、HTML、TEX与LATEX,把连续的空白字符(如空格符、换行符、tab符等)视作一个空格字符。

不间断空格最重要的作用就是 换行时不被打断:

比如:Mr Green , 你肯定不希望看到换行时被打断的

Mr
Green.    

又或者速度 12 m/s, 如果变成这样:

12
m/s.

而是即使有空格,换行后,空格前后两个词 也出现在同一行

多行文本有最大数量限制

往多行文本插入数据的时候,一定要注意一下这个数据量的大小与多行文本最大数量之间的关系,若数据量>大于限制量,则插入失败。
多行文本的数量取值范围:0 ~ 1048576
默认2000

组织服务查询有限制,最多5000条

QueryExpression account = new QueryExpression("account");
account.ColumnSet.AddColumns("accountid", "new_invoicetelephone");
account.Criteria.AddCondition("statecode", ConditionOperator.Equal, 0);
var accountList = this.service.RetrieveMultiple(account);
Console.WriteLine(accountList.Entities.Count);

//客户主档数据
string sql = @"SELECT accountid,new_invoicetelephone,new_invoceadress,accountcategorycode
            FROM account
            WHERE statecode=0 and new_filestatus=2";
DataTable dt = this.crmBroker.Query(sql);
Console.WriteLine("===================================");
Console.WriteLine($"即将初始化【{dt.Rows.Count}】条数据");
Console.WriteLine("===================================");
Console.ReadLine();


   转载规则


《解BUG心得分享》 LoveBin 采用 知识共享署名 4.0 国际许可协议 进行许可。
  目录