1

我正在构建一个旨在集成到表单中的 Silverlight Web 资源,它需要了解以下所有信息:

  • 当前用户的id
  • 当前用户所属团队的id
  • 当前用户的安全角色 id

我正在以一种早期绑定的方式工作,向 OData 端点 ( http://server/org/XRMservices/2011/OrganizationData.svc) 添加了一个服务引用,这反过来为我提供了上下文(让我们命名它cmtestcontext,这是它在代码中的实际名称)。

我通过这个类访问数据(我没有创建它,我前段时间只是从网上搜索到它:这是一个精简的、保持简短的版本)

public class QueryInterface
{    
    //NOTE: ServiceReference1 is the name of the OData service reference
    //Add Service Reference -> point to CRM OData url
    public ServiceReference1.cmtextcontext CrmContext;
    public QueryInterface()
    {
        var crmServerUrl = (string)GetContext().Invoke("getServerUrl");
        if (crmServerUrl.EndsWith("/")) crmServerUrl = crmServerUrl.Substring(0, crmServerUrl.Length - 1);
        Uri ODataUri = new Uri(crmServerUrl + "/xrmservices/2011/organizationdata.svc/", UriKind.Absolute);
        CrmContext = new cmtestContext(ODataUri) { IgnoreMissingProperties = true };
    }   
}

该类允许我在一行中进行排序,如下所示(实际代码片段包含在一个虚拟方法中以使其可复制粘贴):

void RetrieveAllInformationFromCRM()
{
    QueryInterface qi = new QueryInterface();
    List<Guid> allData = new List<Guid>();

    //NOTE: STEP 1 - USER ID
    //NOTE: Since this is a web resource, I can cheat and use Xrm.Page.context.getUserId()
    //NOTE: Remove the extra '{}' from the result for it to be parsed!
    allData.Add(new Guid(qi.GetContext().Invoke("getUserId").ToString().Substring(1,36)));

    //NOTE: STEP 2a - TEAM MEMBERSHIP FOR USER
    //NOTE: TeamMembership entity links users to teams in a N:N relationship
    qi.crmContext.TeamMembershipSet.BeginExecute(new AsyncCallback((result) =>
    {
        var teamMemberships = qi.crmContext.TeamMembershipSet.EndExecute(result)
                              .Where(tm => tm.TeamId.HasValue && (tm.SystemUserId ?? Guid.Empty) == userId)
                              .Select(tm => tm.TeamId.Value);

        //NOTE: STEP 2b - TEAMS RELATED TO TEAMMEMBERSHIPS
        qi.crmContext.TeamSet.BeginExecute(new AsyncCallback((result2) =>
        {
            var teamDetails = qi.crmContext.TeamSet.EndExecute(result2)
                              .Where(t => teamMemberships.Contains(t.TeamId));

            foreach (var team in teamDetails) 
                allData.Add(team.TeamId);

            //NOTE: FINAL STEP - allData is filled and ready to be used.

        }), null);
    }), null);
}

在上面的代码中,myFINAL STEP拾取allData并处理它,然后流程继续进行。我担心的是,如果/当我需要修改这个“阅读器”方法时,我将不得不剪切并粘贴“最终”代码,以确保它被放置在所有阅读之后。如果我可以让阅读彼此跟随,我会更喜欢它,所以我可以这样做:

void MyReaderMethod()
{
     ReadEverything();
     ProcessData();
}

基本上,您可以等待请求完成吗?挂起 UI 不是问题,我只需将代码BackgroundWorker与“请稍候”飞溅一起包装。

4

1 回答 1

0

最好的(IMO)是将异步方法调用(Silverlight 的要求)转换为基于任务的调用。通过任务,您可以轻松地将查询与结果操作分开。

然后使用 Async BCL(通过 nuget),您可以使用 async/await(如果您不使用 VS2012,那么 Tasks 仍然可以更好地使用,您只需要使用延续)

此示例用于后期绑定,但您可以根据需要对其进行修改

 public Task<OrganizationResponse> ExecuteAsync(OrganizationRequest request)
        {
            return Task.Factory.FromAsync<OrganizationResponse>(
                (callback, state) => Begin(() => service.BeginExecute(request, callback, state)),
                   service.EndExecute,
                    null);
        }

然后你可以像这样使用它

 async void MyReaderMethod()
    {
         //TODO:wrap in try/catch
         var result = await ExecuteAsync( ... );
         ProcessData(result);
    }

或者对于 VS 2010

 void MyReaderMethod()
        {
            ExecuteAsync( ... ).ContinueWith(task =>{

               //TODO: Error handling
               ProcessData(task.Result);

               });

        }
于 2013-08-28T15:47:26.723 回答