使用Odata检索集合

时间:2014-05-02 22:50:12

标签: c# silverlight silverlight-4.0 dynamics-crm odata

我正在尝试根据Silverlight控件中的Dynamics CRM中的Id检索一组实体。

我不知道将从查询中返回多少实体,但CRMs Rest服务每页只返回50条记录。因此,您必须继续构建集合,直到没有剩余页面可以从中检索。

我一直试图弄清楚如何让MainPage知道检索已经完成,并且没有剩余的记录要检索。我理想的是希望能够做到:

var opps = _crmManager.RetrieveOpportunities(accountId)
foreach (var opp in opps)
{
    //do stuff here
}

我甚至不确定在这种情况下是否可行。 如果这是不可能的,我猜我将不得不做类似的事情:

_crmManager.OpportunitiesLoaded += OpportunitiesLoaded
private void OpportunitiesLoaded(sender s, EventArgs e)
{
    foreach (var opp in _crmManager.Opportunities)
    {
        //Do work here
    }
}

如果是这种情况,如何判断我的实体何时被完全检索并触发事件?

到目前为止我有这个设置:

//CrmManager.cs
private DataServiceCollection<Opportunity> _opportunity;
public DataServiceCollection<Opportunity> Opportunities
{
    get { return _opportunity;  }
    set { _opportunity= value; }
}

public void RetrieveOpportunities(Guid accountId)
{
    try
        {
            DataServiceQuery<Opportunity> query = (DataServiceQuery<Opportunity>)_context.OpportunitySet
                .AddQueryOption("$filter", "AccountId/Id eq guid'" + accountId + "'");

            query.BeginExecute(ProcessPages<Opportunity>, new PagingContext<Opportunity>()
            {
                ServiceContext = _context,
                Query = query,
                PageProcessor = delegate(DataServiceCollection<Opportunity> results)
                {
                    try
                    {
                        if (null == Opportunities)
                        {
                            Opportunities= new DataServiceCollection<Opportunity>(_context);
                            Opportunities.Load(results);
                        }
                        else
                        {
                            for (int i = 0; i < results.Count; i++)
                            {
                                Opportunities.Add(results[i]);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        //TODO catch
                    }

                    return true;
                }
            });
        }
        catch (SystemException ex)
        {
            //TODO Catch
        }
}
//
private static void ProcessPages<T>(IAsyncResult result)
{
    try
    {
        PagingContext<T> context = (PagingContext<T>)result.AsyncState;

        QueryOperationResponse<T> response;
        if (null == context.Query)
        {
            response = (QueryOperationResponse<T>)context.ServiceContext.EndExecute<T>(result);
        }
        else
        {
            response = (QueryOperationResponse<T>)context.Query.EndExecute(result);
            context.Query = null;
        }
         DataServiceCollection<T> results = new DataServiceCollection<T>(response);

        if (null != context.PageProcessor && !context.PageProcessor(results))
        {
            //Stop processing
            return;
        }

        DataServiceQueryContinuation<T> token = results.Continuation;
        if (null == token)
        {
            return;
        }

        context.ServiceContext.BeginExecute(token, ProcessPages<T>, context);
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

它正在使用的小型PagingContext类

sealed class PagingContext<T>
{
    public DataServiceContext ServiceContext { get; set; }

    public DataServiceQuery<T> Query { get; set; }

    public Func<DataServiceCollection<T>, bool> PageProcessor { get; set; }
}

在MainPage上,我目前使用以下方法调用这些方法:

//MainPage.xaml.cs
_crmManager.RetrieveOpportunities(accountId)
foreach( var opportunity in _crmManager.Opportunities)
{
    //Do work here
}

问题是这在某些时候有效。有时,Opportunities集合中有一些(并非所有)项目,它们将对这些项目起作用。其他时候,当我尝试访问它时,它仍然是空的。

非常感谢任何正确方向的帮助或推动。

1 个答案:

答案 0 :(得分:0)

我找不到按照我的意愿去做的方法: 所以我最终在填充集合时触发了一个事件。 我将它添加到CrmManager类:

public delegate void CrmManagerEventHandler(object sender, EventArgs e);
public event CrmManagerEventHandler OpportunitiesPopulated;

然后在同一类的RetrieveOpportunities方法中:

if ((results.Continuation == null) && (OpportunitiesPopulated!= null))
{
    OpportunitiesPopulated(this, e);
}

然后在MainWindow.xaml.cs中,我订阅了这个事件来做我想做的工作。在MainWindow.xaml.cs的设置中:

_manager.OpportunitiesPopulated += OpportunitiesPopulated;

实际方法:

private void OpportunitiesPopulated(object sender, EventArgs e)
{
    //Do all the work here
}

只有在机会完成填充时才会解雇,这是我需要发生的事情。