小编Dar*_*ryl的帖子

如何为CRM 2011插件正确设置C#单元测试?

尝试在CRM 2011中调试插件非常困难.将.pdb文件放在服务器上的正确位置不仅存在问题,而且每次进行编码更改时,都会遇到部署和重新注册插件的麻烦.由于触发器是在CRM本身,因此很难为它创建单元测试.

我目前为一个全新的插件编写单元测试的过程相当缓慢而且错误,但是这样的事情:

  1. 使用SDK插件注册工具注册新插件
  2. 将调试器附加到w3wp.exe,在插件代码中添加一个断点.
  3. 通过注册运行的任何操作触发插件.
  4. 当断点被击中时,将管道的preimage,postimage和目标值序列化为XML文件,然后这将成为我的单元测试的输入.
  5. 停止调试并创建一个新的单元测试,使用RhinoMocks模拟PluginExecutionContext和ServiceProvider,使用序列化的XML文件作为输入参数的存根.
  6. 创建在每个单元测试的开始和结束时运行的方法,这些方法重置(首先尝试删除,然后添加)要处理的单元测试的虚拟数据,然后在测试结束时删除虚拟数据.
  7. 编辑序列化文件以引用虚拟数据,这样我就可以确保插件在每次运行时都能对抗完全相同的数据.
  8. 在单元测试中声明并实例化插件,传入模拟对象
  9. 执行插件,运行其他查询以确保插件执行我期望的工作,断言失败.

这是一件痛苦的事.从得到的图片正确,创造虚拟的数据,并且每个测试运行时将其复位,似乎有需要改进的很多地区.

如何在不必从CRM实际触发插件的情况下对插件进行单元测试,或者首先运行在CRM中调试它的所有箍,并为每个测试创建独特的虚拟数据?如何使用注入来消除在CRM中为每个单元测试删除,创建,测试,验证和删除数据的需要?

2016年更新

这个问题仍然有很多点击,所以我想我会添加两个(我所知道的)开源项目,为单元测试提供Fake CRM实例:

  • FakeXrmEasy - 由Jordi创建(见下面的答案)
    • 主要是伪造的CRM服务
    • 支持插件/工作流程伪造
    • 对FakeItEasy的依赖
    • 伟大的文档
  • XrmUnitTest - 由我自己创建
    • 假CRM服务+更多(假设,实体建设者等)
    • 流畅支持插件/工作流程伪造
    • 没有对任何模拟框架的依赖
    • Sucky文档(我正在研究它)

查看我创建的视频,比较和对比差异.

c# unit-testing dynamics-crm-2011

8
推荐指数
1
解决办法
3478
查看次数

获取XML中的链接实体的聚合计数不会返回0

问题

我有一个Fetch XML查询,它对链接实体的聚合计数不符合预期.基本上我正在返回课程列表,并计算当前为该课程注册的联系人数,但即使没有人注册该课程,我也会得到1个已注册的联系人.如果我注册1个联系人,我得到1个计数.如果我注册了5个联系人,我得到5个计数,所以当没有相关记录时,问题似乎解决了无法得到0的计数.

这是Fetch XML

<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false" aggregate="true">
  <entity name="new_coursesection">
    <attribute name="new_termscheduleid" groupby="true" alias="new_termscheduleid" />
    <attribute name="new_termid" groupby="true" alias="new_termid" />
    <attribute name="new_sectionname" groupby="true" alias="new_sectionname" />
    <attribute name="new_name" groupby="true" alias="new_name" />
    <filter type="and">
      <condition attribute="new_courseid" operator="eq" value="{some guid}" />
      <condition attribute="statecode" operator="eq" value="0" />
    </filter>
    <link-entity name="new_contactcoursesection" from="new_coursesectionid" to="new_coursesectionid" alias="new_contactcoursesection1" link-type="outer">
      <attribute name="new_contactcoursesectionid" aggregate="count" alias="coursecount" />
      <filter>
        <condition attribute="statecode" operator="eq" value="0"/>
      </filter>
      <order alias="coursecount" descending="true" />
    </link-entity>
  </entity>
</fetch>
Run Code Online (Sandbox Code Playgroud)

有没有人遇到这个问题,知道一个解决方法?

fetchxml dynamics-crm-2011

8
推荐指数
1
解决办法
8116
查看次数

CRM 2011插件注册工具的过滤属性有何作用?

我假设对于Update插件,它指定了一个属性列表,如果被更改,则导致插件触发.

因此,如果我每次更新实体时Foo只针对一个过滤属性注册一个插件,CRM会执行检查以查看是否已更新,如果有,则运行我的插件.因此,使用下面的代码,我希望我的插件执行一次.BarFooBar

Foo foo = new Foo();
foo.Bar = 0;
foo.Id = service.Create(foo);
foo.Bar = 1;
service.Update(foo.Bar); // My plugin would execute
service.Update(foo.Bar); // Bar hasn't changed, I would assume the plugin will not  execute
Run Code Online (Sandbox Code Playgroud)

我在这个假设中是对的吗?

dynamics-crm-2011

8
推荐指数
1
解决办法
5458
查看次数

当我的类多次实现IEnumerable <T>时,为什么我不能使用LINQ to Objects?

我有一个有趣的问题,一个类继承自实现IEnumerable的类,但我也希望该类为不同的类型实现IEnumerable.除了IEnumerable扩展方法之外,一切都有效,这意味着默认情况下我不能对对象执行任何LINQ,而不必先进行强制转换.有没有人有任何想法,除了不断铸造?

using System;
using System.Collections.Generic;
using System.Linq;

namespace LinqTesting
{
    public class Trucks<T> : Vehicles, IEnumerable<Truck>
    {    
        public Trucks()
        {    
            // Does Compile
            var a = ((IEnumerable<Truck>)this).FirstOrDefault();
            // Doesn't Compile, Linq.FirstOrDefault not found
            var b = this.FirstOrDefault();
        }    

        public new IEnumerator<Truck> GetEnumerator() { throw new NotImplementedException(); }
    }    

    public class Vehicles : IEnumerable<Vehicle>
    {    
        public IEnumerator<Vehicle> GetEnumerator() { throw new NotImplementedException(); }
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw new NotImplementedException(); }
    }    

    public class Vehicle { }

    public class Truck : Vehicle …
Run Code Online (Sandbox Code Playgroud)

c# ienumerable linq-to-objects

7
推荐指数
2
解决办法
3321
查看次数

将未知值传递给switch语句时,我应该抛出什么类型的Exception

编辑1

更新以使枚举不是方法的参数...

使用switch语句中的枚举会出现这种类型的问题.在示例代码中,开发人员已考虑该程序当前使用的所有国家/地区,但如果将另一个国家/地区添加到Country枚举,则应抛出异常.我的问题是,应该抛出什么类型的异常?

示例代码:

enum Country
{
    UnitedStates, Mexico,
}

public string GetCallingCode(Guid countryId){
    var country = GetCountry(countryId);
    switch (country)
    {
        case Country.UnitedStates:
            return "1";
            break;
        case Country.Mexico:
            return "52";
            break;
        default:
            // What to throw here
        break;
    }
}
Run Code Online (Sandbox Code Playgroud)

我看了看

  • NotImplemented,未实现请求的方法或操作时引发的异常.
  • NotSupported 基类中不支持某些方法,期望这些方法将在派生类中实现.派生类可能只实现基类中的方法的子集,并为不支持的方法抛出NotSupportedException.
    对于有时可能对象执行请求的操作,并且对象状态确定是否可以执行操作的情况,请参阅InvalidOperationException.
  • 如果调用方法失败是由无效参数以外的原因引起的,则使用InvalidOperation .

我的猜测是NotImplemented或Invalid Operation.我应该使用哪一个?有人有更好的选择(我知道滚动你自己总是一个选项)

c# exception-handling

7
推荐指数
1
解决办法
6179
查看次数

除非文件已打开,否则错误的文件和行号不会显示在错误列表中

我有一个解决方案,错误列表中没有显示错误的文件名和行号,除非我打开文件.

我有另一种解决方案,当我构建解决方案时只显示三个错误,并且它们确实显示行号和文件.如果我打开带有错误的文件,则会弹出另外3个错误,但是当我关闭文件时,所有错误都会消失,直到我再次重建.

我从谷歌搜索看到的唯一问题是路径太长或太奇怪,但我不认为这是一个问题.路径C:\TFS\Apps\Rel_2013.7.1\S3\CrmSvcUtil Extensions适用于部分工作的解决方案以及根本不起作用的解决方案C:\TFS\Apps\Rel_2013.7.1\S3.

编辑1

只是为了清楚说明我所看到的内容:我的解决方案中有多个项目,但其中一个项目没有显示错误的文件或行号,除非文件是打开的.

在这个屏幕截图中,我添加了两个哑误差,每个都在不同的项目中,并构建了解决方案.测试项目按预期显示文件和行号.Common项目没有显示文件或行号错误,即使它应该和当我实际打开包含错误的文件时也是如此.警告不显示文件,因为它是项目级警告,而不是文件级警告,这是有道理的.

示例错误

当我打开带有错误的文件时,文件名和行号确实显示,但是出现了不同的错误:

错误显示在其他错误上

如果我将int更改为字符串,则只删除行编号错误.我实际上必须构建以便删除错误.

c# visual-studio-2012

7
推荐指数
1
解决办法
1956
查看次数

当lambda表达式没有时,Linq to CRM(早期绑定)join语句抛出异常

Microsoft linq to CRM提供程序中是否存在错误,或者我正在执行linqToCrm不支持​​的操作?

我有一个简单的函数,确定是否为用户分配了一个不起作用的角色.

public static bool IsSystemUserInRole(Guid systemUserId,
                                      string roleName,
                                      Microsoft.Xrm.Sdk.IOrganizationService service)
{
    using (var crmService = new CrmContext(service))
    {
        return (from sr in crmService.SystemUserRolesSet
                join r in crmService.RoleSet
                    on sr.RoleId.Value equals r.RoleId.Value
                where sr.SystemUserId.Value == systemUserId && r.Name == roleName
                select sr.SystemUserId).FirstOrDefault() != null;
    }
}
Run Code Online (Sandbox Code Playgroud)

但奇怪的是,如果我将它重写为两个lambda表达式,它可以正常工作.

public static bool IsSystemUserInRole(Guid systemUserId,
                                      string roleName,
                                      Microsoft.Xrm.Sdk.IOrganizationService service)
{
    using (var crmService = new CrmContext(service))
    {
        var role = crmService.RoleSet.FirstOrDefault(r => r.Name == roleName);
        return role != null 
                && …
Run Code Online (Sandbox Code Playgroud)

linq dynamics-crm-2011

6
推荐指数
1
解决办法
5705
查看次数

如何在LinqPad中执行ODATA扩展

我正在使用LINQPad连接到本地CRM组织上的ODATA服务,我不知道如何使用LINQPad执行"连接"或遍历关系.

这是我的网址

OrganizationData.svc/New_locationSet?$select=new_state_new_location/new_Region$expand=new_state_new_location
Run Code Online (Sandbox Code Playgroud)

它在浏览器中工作得很好.这是我在LINQPad中所做的:

from l in new_locationSet
from s in l.new_state_new_location
select s.new_Region
Run Code Online (Sandbox Code Playgroud)

但我收到一个错误:

An expression of type 'LINQPad.User.New_state' is not allowed in a subsequent from clause in a query expression with source type 'System.Data.Services.Client.DataServiceQuery<LINQPad.User.New_location>'.  Type inference failed in the call to 'SelectMany'.
Run Code Online (Sandbox Code Playgroud)

有任何想法吗?我发现LINQPad OData文档极其缺乏......

linqpad odata dynamics-crm-2011

6
推荐指数
1
解决办法
4309
查看次数

如何在插件中获取模拟用户ID?

在插件上下文中,有两个用户ID,

  1. InitiatingUserId 它返回实际触发插件的用户的id.
  2. UserId它返回插件实际运行的用户的用户ID.(这是注册插件时指定的用户,或者调用用户,如果它已注册为主叫用户运行)

但我对第三个用户ID感兴趣,该用户ID是执行调用的OrganizationServiceProxy的模拟用户ID.

假设我有一个运行CRM系统管理员帐户的ASP.Net网站,以及对CRM进行的任何调用,使用模拟,查找当前登录到站点的人员的CRM用户ID.

这适用于选择和更新,用户只能看到\更新他们有权使用的权限.但是......如果我创建一个在特定实体更新时触发的插件,如何从插件中查找Asp网站上模拟用户的用户ID?

asp.net plugins dynamics-crm c#-4.0 dynamics-crm-2011

6
推荐指数
1
解决办法
4632
查看次数

如何在FetchXML中创建条件可选

我有一些性能非常慢的SQL报告,因此我们将它们全部转换为FetchXML,但所有SQL报告都具有可选的所有条件,如下所示:

SELECT 
  ...
FROM ...
WHERE (@operator          = 'All' OR Operator          = @operator)
  AND (@new_gen_comp_name = 'All' OR new_gen_comp_name = @new_gen_comp_name)
  ...
Run Code Online (Sandbox Code Playgroud)

在参数值中,All如果用户选择此值,则存在一个值,该条件将被忽略,因此它将从该字段获取所有值.

现在我想在FetchXML中执行此操作,我尝试or在它们之间放置两个带过滤器的条件,一个用于值,另一个包含空值,如下所示:

<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="true">
   <entity name="incident"> 
      ...
      ...
      <filter type="and">
         <filter type="and">
           <condition attribute="createdon" operator="on-or-after" value="@StartDate" /> 
           <condition attribute="createdon" operator="on-or-before" value="@EndDate" /> 
         </filter>
         <filter type="or">
           <condition attribute="new_gen_comp_type" operator="in" value="@new_gen_comp_type" /> 
           <condition attribute="new_gen_comp_type" operator="null" /> 
         </filter>
      </filter>

      ...
      ...
  </entity>
</fetch>
Run Code Online (Sandbox Code Playgroud)

只有当用户选择参数的所有值时,这才能正常工作@new_gen_comp_type,但问题是如果用户只选择特定值,它也会包含空值,这是错误的.

那么,如果用户选择select allSQL中的参数值,有没有办法让这些条件成为可选项?

dynamics-crm reporting-services fetchxml dynamics-crm-2011 dynamics-crm-2013

6
推荐指数
1
解决办法
7486
查看次数