C# 在crm4c中检索自定义实体#

C# 在crm4c中检索自定义实体#,c#,dynamics-crm-4,entities,C#,Dynamics Crm 4,Entities,在我们的CRM环境中,用户与可用小时数实体之间的关系为1:N,该实体表示他们一周的实际可用小时数。我正在寻找一种在c#中检索本周特定团队用户的所有可用时间的方法 我是CRM开发的新手,我环顾了四周,但似乎有很多方法可以做到这一点,我不确定哪种方法最适合 语言是C#,CRM的版本是MS CRM 4.0,我将介绍3位:一般方法、代码本身,然后是代码的一些注释(对代码进行注释以引起对某些内容的注意,但其中一些内容将在代码之外进行进一步解释) 一般方法 正如您所看到的,有几种方法可以完成任务,但对于通过

在我们的CRM环境中,用户与可用小时数实体之间的关系为1:N,该实体表示他们一周的实际可用小时数。我正在寻找一种在c#中检索本周特定团队用户的所有可用时间的方法

我是CRM开发的新手,我环顾了四周,但似乎有很多方法可以做到这一点,我不确定哪种方法最适合


语言是C#,CRM的版本是MS CRM 4.0,我将介绍3位:一般方法、代码本身,然后是代码的一些注释(对代码进行注释以引起对某些内容的注意,但其中一些内容将在代码之外进行进一步解释)

一般方法 正如您所看到的,有几种方法可以完成任务,但对于通过web服务与CRM交互的外部应用程序,可归结为3个主要选项:

  • 使用通过在web服务调用中添加web引用而获得的强类型方法来检索自定义实体(我认为您在前面的问题中提到的方法爆炸式增长……当您拥有大量自定义实体时,情况会变得更糟)
  • 在web服务调用中使用
    DynamicEntity
  • 获取XML
  • 如果你的系统非常简单,你通常可以不使用(1),但我建议使用(2)或(3)中的任何一种。使用(2)意味着您只需要真正记住少数web服务方法,如果您在这些概念得到相当好的贯彻时进入插件或工作流程序集,那么它就是好的。(3) 如果您了解FetchXML并能够形成适当的查询,那么这是很好的

    我通常使用(2)来处理这些事情,这是一种很好的中间方法,正如我所说的,您的代码将很容易转换为插件或工作流程序集。FetchXML的性能相当好,但我从来都不擅长形成查询——稍后我将介绍一些相关技术,但让我们继续(2)

    此外,如果您使用
    DynamicEntity
    ,您不需要刷新web引用,因为您使用它的方式以及它的
    属性
    对象数组(基本上,您以牺牲强键入为代价获得了灵活性),正如您在代码中看到的那样。如果你使用(1),你会得到针对你的自定义实体的强输入,但你必须根据人们对你的实体所做更改的节奏不断刷新你的WebReference

    代码 这是在一个小型控制台应用程序中,我向CRM服务添加了一个WebReference,并进行了一些调用来模拟您的场景。该代码应适用于其他应用程序,如web应用程序。我试着对它进行评论,所以在进入下一节之前,它可能值得一读

    NB.我不认为这是世界上最好的代码,但它似乎确实有效,应该让您开始学习)

    NB2.我犯了一个错误,为web引用调用了我的命名空间
    CrmService
    -请不要犯与我相同的错误…)

    static void Main(字符串[]args)
    {
    CrmService.CrmService svc=新的CrmService.CrmService();
    svc.CrmAuthenticationTokenValue=GetToken();
    svc.UseDefaultCredentials=true;
    #区域1-检索团队中的用户
    RetrieveMembersTeamRequest团队成员REQ=新的RetrieveMembersTeamRequest()
    {
    EntityId=新Guid(“D56E0E83-2198-E211-9900-080027BBE99”),//您需要团队Guid
    返回百分位数=真
    };
    ColumnSet teamMembersReqColumnSet=新ColumnSet();
    teamMembersReqColumnSet.Attributes=新字符串[]{“systemuserid”,“domainname”};
    teamMembersReq.MemberColumnSet=teamMembersReqColumnSet;//不要使用:teamMembersReq.MemberColumnSet=new AllColumns()
    List userIdList=new List();
    RetrieveMembersTeamResponse teamMembersResp=svc.Execute(teamMembersReq)作为RetrieveMembersTeamResponse;
    如果(teamMembersResp!=null)
    {
    BusinessEntity[]usersInTeamAsBusinessEntity=teamMembersResp.BusinessEntityCollection.BusinessEntity;
    List usersinteamasdynetity=usersinteamasbusinenceentity.Select(be=>be as DynamicEntity.ToList();//BusinessEntity不太有用,转换为DynamicEntity
    foreach(用户中的DynamicEntity de到TeamAsdyEntity)
    {
    属性userIdProp=de.Properties.Where(p=>p.Name==“systemuserid”).FirstOrDefault();
    Property domainNameProp=de.Properties.Where(p=>p.Name==“domainname”).FirstOrDefault();
    if(userIdProp!=null)
    {
    KeyProperty userIdKeyProp=userIdProp as KeyProperty;//因为它是实体的唯一标识符
    userIdList.Add(userIdKeyProp.Value.Value);//将其放入列表中供以后使用
    Write(“Key:+userIdKeyProp.Value.Value.ToString());
    }
    if(domainNameProp!=null)
    {
    StringProperty domainNameStringProp=domainNameProp as StringProperty;//因为其数据类型为varchar
    Console.Write(“|域名:”+domainNameStringProp.Value);
    }
    Console.WriteLine();
    }
    }
    #端区
    /*
    *对于这个示例,我创建了一个名为new_availablehours的虚拟实体,它与use(即1个用户,许多新的_可用小时)具有1:N的关系。
    *测试属性包括:
    *-关系属性称为new_userid…这显然链接到systemuser的GUID
    *-有一个名为new_hours的int数据类型属性
    *-有一个名为new_availabilityday的datetime属性
    */
    #从1检索区域:N
    RetrieveMultipleRequest req=新的RetrieveMultipleRequest();
    重新
    
    static void Main(string[] args)
    {
            CrmService.CrmService svc = new CrmService.CrmService();
            svc.CrmAuthenticationTokenValue = GetToken();
            svc.UseDefaultCredentials = true;
    
            #region 1 - Retrieve users in team
            RetrieveMembersTeamRequest teamMembersReq = new RetrieveMembersTeamRequest()
            {
                EntityId = new Guid("D56E0E83-2198-E211-9900-080027BBBE99"), //You'll need the team GUID
                ReturnDynamicEntities = true
            };
    
            ColumnSet teamMembersReqColumnSet = new ColumnSet();
            teamMembersReqColumnSet.Attributes = new string[] { "systemuserid", "domainname" };
    
            teamMembersReq.MemberColumnSet = teamMembersReqColumnSet; //Don't use: teamMembersReq.MemberColumnSet = new AllColumns()
    
            List<Guid> userIdList = new List<Guid>();
            RetrieveMembersTeamResponse teamMembersResp = svc.Execute(teamMembersReq) as RetrieveMembersTeamResponse;
            if (teamMembersResp != null)
            {
                BusinessEntity[] usersInTeamAsBusinessEntity = teamMembersResp.BusinessEntityCollection.BusinessEntities;
                List<DynamicEntity> usersInTeamAsDynEntity = usersInTeamAsBusinessEntity.Select(be => be as DynamicEntity).ToList(); //BusinessEntity not too useful, cast to DynamicEntity
    
                foreach (DynamicEntity de in usersInTeamAsDynEntity)
                {
                    Property userIdProp = de.Properties.Where(p => p.Name == "systemuserid").FirstOrDefault();
                    Property domainNameProp = de.Properties.Where(p => p.Name == "domainname").FirstOrDefault();
    
                    if (userIdProp != null)
                    {
                        KeyProperty userIdKeyProp = userIdProp as KeyProperty; //Because it is the unique identifier of the entity
                        userIdList.Add(userIdKeyProp.Value.Value); //Chuck in a list for use later
                        Console.Write("Key: " + userIdKeyProp.Value.Value.ToString());
                    }
    
                    if (domainNameProp != null)
                    {
                        StringProperty domainNameStringProp = domainNameProp as StringProperty; //Because its data type is varchar
                        Console.Write("| Domain Name: " + domainNameStringProp.Value);
                    }
    
                    Console.WriteLine();
                }
            }
            #endregion
    
            /*
             * For this example I have created a dummy entity called new_availablehours that is in a 1:N relationship with use (i.e. 1 user, many new_available hours). 
             * The test attributes are :
             *      - the relationship attribute is called new_userid...this obviously links across to the GUID from systemuser
             *      - there is an int data type attribute called new_hours
             *      - there is a datetime attribute called new_availabilityday
             */
            #region Retrieve From 1:N
            RetrieveMultipleRequest req = new RetrieveMultipleRequest();
            req.ReturnDynamicEntities = true; //Because we love DynamicEntity
    
            //QueryExpression says what entity to retrieve from, what columns we want back and what criteria we use for selection
            QueryExpression qe = new QueryExpression();
            qe.EntityName = "new_availablehours"; //the entity on the many side of the 1:N which we want to get data from
    
            qe.ColumnSet = new AllColumns(); //Don't do this in real life, limit it like we did when retrieving team members
    
            /*
             * In this case we have 1 x Filter Expression which combines multiple Condition Operators
             * Condition Operators are evaluated together using the FilterExpression object's FilterOperator property (which is either AND or OR)
             * 
             * So if we use AND all conditions need to be true and if we use OR then at least one of the conditions provided needs to be true
             * 
             */
            FilterExpression fe = new FilterExpression();
            fe.FilterOperator = LogicalOperator.And;
    
            ConditionExpression userCondition = new ConditionExpression();
            userCondition.AttributeName = "new_userid"; //The attribute of qe.EntityName which we want to test against
            userCondition.Operator = ConditionOperator.In; //Because we got a list of users previously, the appropriate check is to get records where new_userid is in the list of valid ones we generated earlier
            userCondition.Values = userIdList.Select(s => s.ToString()).ToArray(); //Flip the GUID's to strings (seems that CRM likes that) then set them as the values we want to evaulate
            //OK - so now we have this userCondition where valid records have their new_userid value in a collection of ID's we specify
    
            ConditionExpression dateWeekBound = new ConditionExpression();
            dateWeekBound.AttributeName = "new_availabilityday";
            dateWeekBound.Operator = ConditionOperator.ThisWeek; //ConditionOperator has a whole bunch of convenience operators to deal with dates (e.g. this week, last X days etc) - check them out as they are very handy
    
            /*
             * As an aside, if we didn't want to use the convenience operator (or if none was available) we would have to create a ConditionExpression like:
             * 
             * ConditionExpression dateLowerBound = new ConditionExpression();
             * dateLowerBound.AttributeName = "new_availabilityday";
             * dateLowerBound.Operator = ConditionOperator.OnOrAfter;
             * dateLowerBound.Values = new object[] { <Your DateTime object here> };
             * 
             * And a corresponding one for the upper bound using ConditionOperator.OnOrBefore
             * 
             * Another alternative is to use ConditionOperator.Between. This is flexible for any sort of data, but the format of the Values array will be something like:
             *      ce.Values = new object[] { <lower bound>, <upper bound> };
             */
    
            fe.Conditions = new ConditionExpression[] { userCondition, dateWeekBound }; //Add the conditions to the filter
            qe.Criteria = fe; //Tell the query what our filters are
            req.Query = qe; //Tell the request the query we want to use
    
            RetrieveMultipleResponse resp = svc.Execute(req) as RetrieveMultipleResponse;
            if (resp != null)
            {
                BusinessEntity[] rawResults = resp.BusinessEntityCollection.BusinessEntities;
                List<DynamicEntity> castedResults = rawResults.Select(r => r as DynamicEntity).ToList();
    
                foreach (DynamicEntity result in castedResults)
                {
                    Property user = result.Properties.Where(p => p.Name == "new_userid").FirstOrDefault();
                    Property hours = result.Properties.Where(p => p.Name == "new_hours").FirstOrDefault();
    
                    if (user != null)
                    {
                        LookupProperty relationshipProperty = user as LookupProperty; //Important - the relationship attribute casts to a LookupProperty
                        Console.Write(relationshipProperty.Value.Value.ToString() + ", ");
                    }
    
                    if (hours != null)
                    {
                        CrmNumberProperty hoursAsCrmNumber = hours as CrmNumberProperty; //We also have CrmFloatProperty, CrmDecimalProperty etc if the attribute was of those data types
                        Console.Write(hoursAsCrmNumber.Value.Value);
                    }
    
                    Console.WriteLine();
                }
            }
            #endregion
    
            Console.ReadLine();
        }
    
        static CrmAuthenticationToken GetToken()
        {
            CrmAuthenticationToken token = new CrmAuthenticationToken();
            token.AuthenticationType = 0; //Active Directory
            token.OrganizationName = "DevCRM";
    
            return token;
        }