簡體   English   中英

在C#中使用CSOM從選定的行中動態加載Project Server列

[英]Using CSOM in C# to Dynamically Load Project Server Columns From Selected Rows

我使用CSOM .NET從Project Server 2013加載任務對象,我需要

  • 過濾任務,以便僅返回其中的一部分,並且
  • 僅加載由用戶在運行時指定的任務列的子集。

我發現這篇文章顯示了如何加載一組動態列,並且對我的第二個要求非常有效。 但是,我不能想出一個可行的LINQ語法列的選擇和行篩選相結合。

在下面的示例中,我只需要加載摘要任務的“行”(其中t.IsSummarytrue ),並且只加載NameStartFinish列。

引用的帖子中的以下代碼僅加載我需要的三列:

foreach (string fieldName in new List<string>(){"Name","Start","Finish"});
{
  ctx.Load(ctx.Tasks,c => c.Include(t => t[fieldName]));
}
ctx.ExecuteQuery();  

但是,當我嘗試以唯一對我有意義的語法結合where()include()時,我會通過foreach循環在第二次迭代時收到InvalidQueryExpressionException :“不支持查詢表達式。”

foreach (string fieldName in new List<string>(){"Name","Start","Finish"});
{
    ctx.Load(ctx.Tasks,
    c => c.Where(t => t.IsSummary),
    c => c.Include(t => t[fieldName])
    );
}

ctx.ExecuteQuery();

如果我反轉whereinclude子句的順序,則會收到相同的錯誤。 如果我將where子句拉到字段名稱的循環之外,並使其成為單獨的Load調用,則摘要任務行過濾有效,但是我無法動態選擇任務字段。 LINQ for CSOM中必須有一個滿足這兩個要求的語法。 進行此類查詢的正確語法是什么?

下面的示例演示如何在SharePoint CSOM API中應用選擇和篩選運算符:

var list = ctx.Web.Lists.GetByTitle(listTitle);
var items = list.GetItems(CamlQuery.CreateAllItemsQuery());

var result = ctx.LoadQuery(items.Where(i => (bool)i["IsSummary"]).Include(i => i["Name"], i => i["Start"], i => i["Finish"]));
ctx.ExecuteQuery();

foreach (var item in result)
{
    Console.WriteLine(item["Name"]);    
}

因此,我相信Project Server CSOM API支持以下表達式:

var result = ctx.LoadQuery(ctx.Tasks.Where(t => (bool)t["IsSummary"]).Include(t => i["Name"], t => t["Start"], t => t["Finish"]));
ctx.ExecuteQuery();

我使用表達式樹來回答這個問題,表達式樹使您可以過濾一組行並根據僅在運行時才知道的參數選擇一組列。 在下面的示例中,我模擬了在運行時查找需要過濾IsSummary列上的任務,並且僅應檢索五個列IdNameStartIsSubProjectFinish的情況 這是代碼:

        using System.Linq.Expressions;

        // Input parms discovered at runtime
        string filterColumnName = "IsSummary";
        List<string> columnNames = new List<string>(
          new[] { "Id", "Name", "Start", "IsSubProject", "Finish" });

        //  Get the client object for the Published Project matching projGuid
        ctx.Load(ctx.Projects, c => c.Where(p => p.Id == projGuid));
        ctx.ExecuteQuery();
        PublishedProject proj = ctx.Projects.Single();

        // Compute the expression tree for filtering the task rows
        var taskParm = Expression.Parameter(typeof(PublishedTask), "t");
        var predicate = Expression.PropertyOrField(taskParm, filterColumnName);
        var filterExpression = Expression.Lambda<
                Func<PublishedTask, bool>>(predicate, taskParm);

        //  Dynamically generate expression tree for each column to be included
        var colSelectionList = new List<Expression<
                Func<PublishedTask, object>>>();

        foreach (var colName in columnNames)
        {
            var fldExpr = Expression.PropertyOrField(taskParm, colName);
            var fldAsObjExpr = Expression.Convert(fldExpr, typeof(object));
            var colSelectorExpr = Expression.Lambda<
                 Func<PublishedTask, object>>(fldAsObjExpr, taskParm);
            colSelectionList.Add(colSelectorExpr);
        }

        //  Create query using LoadQuery (Load does not work here)                  
        var taskList = ctx.LoadQuery(proj.Tasks
                        .Where(filterExpression)
                        .Include(colSelectionList.ToArray())
                        );

        //  Execute the query
        ctx.ExecuteQuery();
        // taskList now contains just the filtered rows and selected columns

我希望這可以幫助其他堅持使用CSOM為Project Server進行此操作的人。 我發現這兩個參考資料很有幫助: 在MSDN“匈牙利SharePoint極客的第二人生”中

..吉姆

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM