You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SharePoint中如何用C#的CAML查询关联两个列表并获取嵌套对象?

SharePoint跨列表关联查询并构建嵌套对象方案

首先明确:CAML本身不支持跨列表的JOIN查询并直接返回嵌套结构的结果,因为SharePoint的CAML查询是单列表维度的,没法一次性关联两个列表并返回包含子列表数据的嵌套对象。你需要分两步处理:先查询主列表数据,再批量查询关联的子列表数据,最后在代码层面完成数据的嵌套映射。

以下是具体的C#实现方案(基于SharePoint CSOM):

1. 定义实体类

先定义对应列表数据的实体,方便后续处理:

// Page列表对应的实体
public class PageModel
{
    public int Id { get; set; }
    public string Title { get; set; }
    // 嵌套的Fragment列表
    public List<FragmentModel> Fragments { get; set; } = new List<FragmentModel>();
}

// Fragment列表对应的实体
public class FragmentModel
{
    public int TableAId { get; set; }
    public string Article { get; set; }
}

2. 分两次查询并关联数据

步骤1:查询Page列表的所有数据

using (var ctx = new ClientContext("你的SharePoint站点URL"))
{
    // 根据环境配置认证方式(如用户名密码、App权限等)
    ctx.Credentials = new SharePointOnlineCredentials("用户名", "密码的SecureString");

    // 查询Page列表
    var pageList = ctx.Web.Lists.GetByTitle("Page");
    var pageQuery = CamlQuery.CreateAllItemsQuery();
    var pageItems = pageList.GetItems(pageQuery);
    ctx.Load(pageItems, items => items.Include(
        item => item.Id,
        item => item["Title"]
    ));
    ctx.ExecuteQuery();

    // 转换为PageModel列表
    var pageModels = pageItems.Select(item => new PageModel
    {
        Id = item.Id,
        Title = item["Title"]?.ToString() ?? string.Empty
    }).ToList();

步骤2:批量查询Fragment列表并关联到对应Page

// 收集所有Page的Id,用于批量过滤Fragment
    var pageIds = pageModels.Select(p => p.Id).ToList();
    if (!pageIds.Any())
    {
        // 没有Page数据,直接返回
        return pageModels;
    }

    // 构建CAML查询,过滤TableAId在PageIds中的Fragment
    var fragmentList = ctx.Web.Lists.GetByTitle("Fragment");
    var camlBuilder = new StringBuilder();
    camlBuilder.Append("<View><Query><Where><In><FieldRef Name='TableAId'/>");
    camlBuilder.Append("<Values>");
    foreach (var id in pageIds)
    {
        camlBuilder.Append($"<Value Type='Number'>{id}</Value>");
    }
    camlBuilder.Append("</Values></In></Where></Query></View>");

    var fragmentQuery = new CamlQuery { ViewXml = camlBuilder.ToString() };
    var fragmentItems = fragmentList.GetItems(fragmentQuery);
    ctx.Load(fragmentItems, items => items.Include(
        item => item["TableAId"],
        item => item["article"]
    ));
    ctx.ExecuteQuery();

    // 转换为FragmentModel列表
    var fragmentModels = fragmentItems.Select(item => new FragmentModel
    {
        TableAId = int.Parse(item["TableAId"].ToString()),
        Article = item["article"]?.ToString() ?? string.Empty
    }).ToList();

步骤3:在内存中关联数据,构建嵌套结构

// 将Fragment关联到对应的Page
    foreach (var page in pageModels)
    {
        page.Fragments = fragmentModels.Where(f => f.TableAId == page.Id).ToList();
    }

    // 现在pageModels就是包含嵌套Fragment的Page对象列表
}

补充说明

  • 如果你的TableAId是Lookup类型字段(关联到Page的Id),那么CAML查询中FieldRef的Name要对应Lookup字段的内部名称,并且Value的Type要改为Lookup,同时用LookupId属性指定匹配Id:
    <Value Type='Lookup' LookupId='True'>{id}</Value>
    
  • 这种分两次查询的方式比循环查询每个Page对应的Fragment效率高很多,因为批量查询减少了请求次数。
  • 如果你之前尝试用CAML的<Join>元素,它仅用于在查询主列表时返回关联列表的部分字段(扁平化结果),没法返回嵌套的列表结构,所以无法直接得到你想要的单个嵌套对象。

内容的提问来源于stack exchange,提问作者Mike

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 22:10:42