From 65d501d05e425e68b6469b71e4f397e299cb48c2 Mon Sep 17 00:00:00 2001 From: Sergei Sergeev Date: Thu, 25 Nov 2021 15:12:11 +0300 Subject: [PATCH] Updated docs with more information regarding IQuerable. Update xml code comments to include links to the documentation. --- docs/using-the-sdk/basics-getdata.md | 21 +-- docs/using-the-sdk/basics-iqueryable.md | 135 ++++++++++++++++++ docs/using-the-sdk/toc.yml | 2 + .../Model/Security/Public/ISharePointGroup.cs | 4 + .../Model/SharePoint/Core/Public/IComment.cs | 7 + .../SharePoint/Core/Public/IContentType.cs | 10 +- .../Model/SharePoint/Core/Public/IFile.cs | 4 + .../Model/SharePoint/Core/Public/IFolder.cs | 4 + .../Core/Public/ILikedByInformation.cs | 7 +- .../Model/SharePoint/Core/Public/IList.cs | 19 ++- .../Model/SharePoint/Core/Public/IListItem.cs | 7 + .../Core/Public/IListItemVersion.cs | 4 + .../Core/Public/IRegionalSettings.cs | 5 + .../Core/Public/ISecurableObject.cs | 4 + .../Model/SharePoint/Core/Public/ISite.cs | 13 ++ .../Model/SharePoint/Core/Public/IWeb.cs | 42 +++++- .../Model/SharePoint/Taxonomy/Public/ITerm.cs | 4 + .../SharePoint/Taxonomy/Public/ITermGroup.cs | 4 + .../SharePoint/Taxonomy/Public/ITermSet.cs | 3 + .../SharePoint/Taxonomy/Public/ITermStore.cs | 4 + src/sdk/PnP.Core/Model/Teams/Public/ITeam.cs | 13 ++ .../Model/Teams/Public/ITeamChannel.cs | 7 + 22 files changed, 309 insertions(+), 14 deletions(-) create mode 100644 docs/using-the-sdk/basics-iqueryable.md diff --git a/docs/using-the-sdk/basics-getdata.md b/docs/using-the-sdk/basics-getdata.md index 4d00d18374..583a51f99f 100644 --- a/docs/using-the-sdk/basics-getdata.md +++ b/docs/using-the-sdk/basics-getdata.md @@ -51,8 +51,8 @@ using (var context = await pnpContextFactory.CreateAsync("SiteToWorkWith")) // Data is loaded into the context await context.Web.LoadAsync(p => p.Title, p => p.Lists); - // We're using AsRequested() to query the already loaded domain models, if not a new query would - // issued to load the lists + // We're using AsRequested() to query the already loaded domain models, + // otherwise a new query would be issued to load the lists foreach (var list in context.Web.Lists.AsRequested()) { // do something with the list @@ -75,8 +75,8 @@ using (var context = await pnpContextFactory.CreateAsync("SiteToWorkWith")) // Load the data into variable var web = await context.Web.GetAsync(p => p.Title, p => p.Lists); - // We're using AsRequested() to query the already loaded domain models, if not a new query would - // issued to load the lists + // We're using AsRequested() to query the already loaded domain models, + // otherwise a new query would be issued to load the lists foreach (var list in web.Lists.AsRequested()) { // do something with the list @@ -92,23 +92,26 @@ Previous chapter showed how to load data starting from a single model (e.g. load using (var context = await pnpContextFactory.CreateAsync("SiteToWorkWith")) { // Option A: Load the Lists using a model load => no filtering option - var lists = await context.Web.GetAsync(p => p.Title, p => p.Lists); + var web = await context.Web.GetAsync(p => p.Title, p => p.Lists); + var lists = web.Lists.AsRequested(); // Option B: Load the Lists using a LINQ query ==> filtering is possible, // only lists with title "Site Pages" are returned var lists = await context.Web.Lists.Where(p => p.Title == "Site Pages").ToListAsync(); // Option C: we assume there's only one list with that title so we can use FirstOrDefaultAsync - var sitePagesList = await context.Web.Lists.Where(p => p.Title == "Site Pages").FirstOrDefaultAsync(); + var sitePagesList = await context.Web.Lists.FirstOrDefaultAsync(p => p.Title == "Site Pages"); } ``` Like with loading the model in the previous chapter you've two ways of using the data: query the data that was loaded in the context or query the data loaded into a variable: -Below sample shows the various options for loading and using collections. +Below sample shows the various options for loading and using collections. > [!Note] -> - When you want to enumerate or query (via LINQ) already loaded data you need to first use the `AsRequested()` method to return the domain model objects as an `IEnumerable`. +> +> - When you want to enumerate or query (via LINQ) already loaded data you need to first use the `AsRequested()` method to return the domain model objects as an `IList`. +> - `IQueryable` is an interface used by almost all collections (like `Lists`, `Fields`, etc.) in PnP Core SDK. It's very powerful, but should be used carefully to avoid some common performance pitfalls. Read [IQueryable performance considerations](basics-iqueryable.md) to learn more. > - When using a filter via the `Where` LINQ statement then always use an operator: `Where(p => p.BoolProperty == true)` works, but `Where(p => p.BoolProperty)` is ignored. ```csharp @@ -127,7 +130,7 @@ using (var context = await pnpContextFactory.CreateAsync("SiteToWorkWith")) // are not loaded into the context var lists = await context.Web.Lists.Where(p => p.Title == "Site Pages").ToListAsync(); - foreach(var list in lists.AsRequested()) + foreach(var list in lists) { // Use list } diff --git a/docs/using-the-sdk/basics-iqueryable.md b/docs/using-the-sdk/basics-iqueryable.md new file mode 100644 index 0000000000..ddabd7bf79 --- /dev/null +++ b/docs/using-the-sdk/basics-iqueryable.md @@ -0,0 +1,135 @@ +# [`IQueryable`](https://docs.microsoft.com/en-us/dotnet/api/system.linq.iqueryable) performance considerations + +In the [Requesting model collections](basics-getdata.md#requesting-model-collections) section you saw quite a lot of different examples of how to query collections. Almost all collections inside PnP Core SDK implement an [`IQueryable`](https://docs.microsoft.com/en-us/dotnet/api/system.linq.iqueryable) interface. + +Thanks to this you can use LINQ expressions to dynamically filter or asynchronously load collection elements on demand. All your LINQ expressions will be accurately translated to the REST OData query operations (like `$filter`, `$select`, `$expand`, etc). + +Having below code: + +```csharp +var lists = await context.Web.Lists + .Where(l => l.Hidden == false && l.TemplateType == ListTemplateType.DocumentLibrary) + .QueryProperties(p => p.Title, p => p.TemplateType, p => p.ContentTypes.QueryProperties(p => p.Name)).ToListAsync(); +``` + +upon execution will be translated to the below REST OData query: + +```bash +_api/web/lists?$select=Id,Title,BaseTemplate,ContentTypes/Name,ContentTypes/StringId&$expand=ContentTypes&$filter=(BaseTemplate+eq+101) +``` + +It's a very powerful feature, however let's take a closer look at this technique to avoid some common performance issues. + +> [!Important] +> +> The most important rule of `IQueryable` is that an `IQueryable` doesn't fire a request when it's declared, but only when it's enumerated over (inside foreach cycle or when calling `ToList()`/`ToListAsync()`). + +## Loading collections into the PnPContext + +Let's have a sample query to get a web's lists: + +❌ *not efficient:* + +```csharp +// All lists loaded into the context +await context.Web.LoadAsync(p => p.Lists); + +foreach (var list in context.Web.Lists) +{ + // do something with the list here +} +``` + +What's wrong with this code? It works just fine, however it sends two identical HTTP requests to the SharePoint server to get lists (one in `LoadAsync(p => p.Lists)` and the second one in the `foreach` cycle). Why does it happen? Because `Lists` property implements `IQueryable`, inside `foreach` cycle you effectively enumerate the `IQueryable`, as a result, it sends an HTTP request to get data. + +How to fix the code? Use `AsRequested()`: + +✅ *better:* + +```csharp +// All lists loaded into the context +await context.Web.LoadAsync(p => p.Lists); + +foreach (var list in context.Web.Lists.AsRequested()) +{ + // do something with the list here +} +``` + +As mentioned earlier, `AsRequested()` method returns an already loaded collection of items, you should use this method to avoid multiple unnecessary HTTP requests. In this case, we enumerate a collection loaded in memory before. + +Alternatively, you can also use just one cycle without `LoadAsync(p => p.Lists)`: + +✅ *better:* + +```csharp +await foreach (var list in context.Web.Lists) +{ + // do something with list here +} +``` + +In this case, list collection will be requested at the beginning of the `foreach` cycle. Do remember though, that if you iterate over collection again somewhere in your code path, an additional request will be sent. + +## Load related properties + +The below code has a similar problem with the query efficiency: + +❌ *not efficient:* + +```csharp +var list = await context.Web.Lists.GetByTitleAsync("Documents", l => l.Fields); +var fields = await list.Fields.Where(l => l.InternalName.StartsWith("tax")).ToListAsync(); +``` + +The first line loads a list by title and also loads related property - all list fields. On the second line we again send HTTP request to further filter fields. But what we need instead is to filter already loaded fields: + +```csharp +var fields = list.Fields.AsRequested().Where(l => l.InternalName.StartsWith("tax")).ToList(); +``` + +To make it even more efficient, you should change it like this: + +✅ *better:* + +```csharp +var list = await context.Web.Lists.GetByTitleAsync("Documents"); +var fields = await list.Fields.Where(l => l.InternalName.StartsWith("tax")).ToListAsync(); +``` + +It doesn't make sense to load all related fields with the list request. Thus we simply send a separate request with a filter (will be translated to the `$filter=startswith` OData query) to get desired fields. + +## Cycles and/or method calls + +Could you guess what's the problem with the below code: + +❌ *not efficient:* + +```csharp +var filteredList = context.Web.Lists.Where(l => l.TemplateType == ListTemplateType.DocumentLibrary); + +for (int i = 0; i < 10; i++) +{ + DoSmth(filteredList); +} + +private bool DoSmth(IEnumerable lists) +{ + foreach (var list in lists) + { + // do smth with list + } +} +``` + +It also works just fine, however has an issue, that the above code sends 10 HTTP requests to get lists data. The `filteredList` is an instance of `IQueryable`, that's why it doesn't execute the request immediately, but only inside the `foreach` cycle in the `Check` function. Every time we visit the function, we send an HTTP request to get lists. + +How to fix it? Change the filter query so that it executes immediately using `ToList()` or `ToListAsync()` methods: + +✅ *better:* + +```csharp +var filteredList = await context.Web.Lists.Where(l => l.TemplateType == ListTemplateType.DocumentLibrary).ToListAsync(); +``` + +The code above executes the request instantly and loads all items into the memory, thus we don't have the issue with multiple HTTP queries. The type of `filteredList` will be `IList`, not `IQueryable`. diff --git a/docs/using-the-sdk/toc.yml b/docs/using-the-sdk/toc.yml index fd0f9327c4..6d5ed7c4a3 100644 --- a/docs/using-the-sdk/toc.yml +++ b/docs/using-the-sdk/toc.yml @@ -8,6 +8,8 @@ href: basics-getdata-paging.md - name: Adding, updating and deleting data href: basics-addupdatedelete.md + - name: IQueryable performance considerations + href: basics-iqueryable.md - name: Advanced PnPContext use href: basics-context.md - name: Batching requests diff --git a/src/sdk/PnP.Core/Model/Security/Public/ISharePointGroup.cs b/src/sdk/PnP.Core/Model/Security/Public/ISharePointGroup.cs index 42dd15cb20..f840fe547a 100644 --- a/src/sdk/PnP.Core/Model/Security/Public/ISharePointGroup.cs +++ b/src/sdk/PnP.Core/Model/Security/Public/ISharePointGroup.cs @@ -1,4 +1,5 @@ using PnP.Core.Services; +using System.Linq; using System.Threading.Tasks; namespace PnP.Core.Model.Security @@ -61,6 +62,9 @@ public interface ISharePointGroup : IDataModel, IDataModelGet< /// /// Members of this group + /// Implements .
+ /// See Requesting model collections + /// and IQueryable performance considerations to learn more. ///
public ISharePointUserCollection Users { get; } diff --git a/src/sdk/PnP.Core/Model/SharePoint/Core/Public/IComment.cs b/src/sdk/PnP.Core/Model/SharePoint/Core/Public/IComment.cs index fe41f8b316..5fbbd249e6 100644 --- a/src/sdk/PnP.Core/Model/SharePoint/Core/Public/IComment.cs +++ b/src/sdk/PnP.Core/Model/SharePoint/Core/Public/IComment.cs @@ -1,5 +1,6 @@ using PnP.Core.Model.Security; using System; +using System.Linq; using System.Threading.Tasks; namespace PnP.Core.Model.SharePoint @@ -73,6 +74,9 @@ public interface IComment : IDataModel, IDataModelGet, IData /// /// List of users who have liked the comment. + /// Implements .
+ /// See Requesting model collections + /// and IQueryable performance considerations to learn more. ///
public ICommentLikeUserEntityCollection LikedBy { get; } @@ -83,6 +87,9 @@ public interface IComment : IDataModel, IDataModelGet, IData /// /// List of users who are at mentioned in this comment. + /// Implements .
+ /// See Requesting model collections + /// and IQueryable performance considerations to learn more. ///
public ICommentLikeUserEntityCollection Mentions { get; } diff --git a/src/sdk/PnP.Core/Model/SharePoint/Core/Public/IContentType.cs b/src/sdk/PnP.Core/Model/SharePoint/Core/Public/IContentType.cs index 04909044eb..4d6054b3d8 100644 --- a/src/sdk/PnP.Core/Model/SharePoint/Core/Public/IContentType.cs +++ b/src/sdk/PnP.Core/Model/SharePoint/Core/Public/IContentType.cs @@ -1,4 +1,6 @@ -namespace PnP.Core.Model.SharePoint +using System.Linq; + +namespace PnP.Core.Model.SharePoint { /// /// Public interface to define a Content Type object of SharePoint Online @@ -129,11 +131,17 @@ public interface IContentType : IDataModel, IDataModelGet /// Gets the collection of field links of the Content Type. + /// Implements .
+ /// See Requesting model collections + /// and IQueryable performance considerations to learn more. ///
public IFieldLinkCollection FieldLinks { get; } /// /// Gets the collection of fields of the Content Type. + /// Implements .
+ /// See Requesting model collections + /// and IQueryable performance considerations to learn more. ///
public IFieldCollection Fields { get; } diff --git a/src/sdk/PnP.Core/Model/SharePoint/Core/Public/IFile.cs b/src/sdk/PnP.Core/Model/SharePoint/Core/Public/IFile.cs index cde74bc229..88cd3bc654 100644 --- a/src/sdk/PnP.Core/Model/SharePoint/Core/Public/IFile.cs +++ b/src/sdk/PnP.Core/Model/SharePoint/Core/Public/IFile.cs @@ -2,6 +2,7 @@ using PnP.Core.Services; using System; using System.IO; +using System.Linq; using System.Threading.Tasks; namespace PnP.Core.Model.SharePoint @@ -181,6 +182,9 @@ public interface IFile : IDataModel, IDataModelGet, IDataModelLoad /// /// Gets a value that returns a collection of file version objects that represent the versions of the file. + /// Implements .
+ /// See Requesting model collections + /// and IQueryable performance considerations to learn more. ///
public IFileVersionCollection Versions { get; } diff --git a/src/sdk/PnP.Core/Model/SharePoint/Core/Public/IFolder.cs b/src/sdk/PnP.Core/Model/SharePoint/Core/Public/IFolder.cs index 11760a4232..89cf4e4167 100644 --- a/src/sdk/PnP.Core/Model/SharePoint/Core/Public/IFolder.cs +++ b/src/sdk/PnP.Core/Model/SharePoint/Core/Public/IFolder.cs @@ -1,5 +1,6 @@ using PnP.Core.Services; using System; +using System.Linq; using System.Threading.Tasks; namespace PnP.Core.Model.SharePoint @@ -82,6 +83,9 @@ public interface IFolder : IDataModel, IDataModelGet, IDataMod /// /// Gets the collection of list folders contained in the list folder. + /// Implements .
+ /// See Requesting model collections + /// and IQueryable performance considerations to learn more. ///
public IFolderCollection Folders { get; } diff --git a/src/sdk/PnP.Core/Model/SharePoint/Core/Public/ILikedByInformation.cs b/src/sdk/PnP.Core/Model/SharePoint/Core/Public/ILikedByInformation.cs index 919339e7a1..f6137e7c11 100644 --- a/src/sdk/PnP.Core/Model/SharePoint/Core/Public/ILikedByInformation.cs +++ b/src/sdk/PnP.Core/Model/SharePoint/Core/Public/ILikedByInformation.cs @@ -1,4 +1,6 @@ -namespace PnP.Core.Model.SharePoint +using System.Linq; + +namespace PnP.Core.Model.SharePoint { /// /// Defines if and who liked a list item. @@ -18,6 +20,9 @@ public interface ILikedByInformation : IDataModel, IDataMod /// /// The people that liked this list item. + /// Implements .
+ /// See Requesting model collections + /// and IQueryable performance considerations to learn more. ///
public ICommentLikeUserEntityCollection LikedBy { get; } } diff --git a/src/sdk/PnP.Core/Model/SharePoint/Core/Public/IList.cs b/src/sdk/PnP.Core/Model/SharePoint/Core/Public/IList.cs index e4502e1dd9..f126ae0f68 100644 --- a/src/sdk/PnP.Core/Model/SharePoint/Core/Public/IList.cs +++ b/src/sdk/PnP.Core/Model/SharePoint/Core/Public/IList.cs @@ -1,7 +1,7 @@ -using PnP.Core.Model.Security; -using PnP.Core.Services; +using PnP.Core.Services; using System; using System.Collections.Generic; +using System.Linq; using System.Linq.Expressions; using System.Threading.Tasks; @@ -233,16 +233,25 @@ public interface IList : IDataModel, IDataModelGet, IDataModelLoad /// /// Collection of list items in the current List object + /// Implements .
+ /// See Requesting model collections + /// and IQueryable performance considerations to learn more. ///
public IListItemCollection Items { get; } /// /// Collection of content types for this list + /// Implements .
+ /// See Requesting model collections + /// and IQueryable performance considerations to learn more. ///
public IContentTypeCollection ContentTypes { get; } /// /// Collection of fields for this list + /// Implements .
+ /// See Requesting model collections + /// and IQueryable performance considerations to learn more. ///
public IFieldCollection Fields { get; } @@ -253,11 +262,17 @@ public interface IList : IDataModel, IDataModelGet, IDataModelLoad /// /// Get a list of the views + /// Implements .
+ /// See Requesting model collections + /// and IQueryable performance considerations to learn more. ///
public IViewCollection Views { get; } /// /// Collection of list webhooks + /// Implements .
+ /// See Requesting model collections + /// and IQueryable performance considerations to learn more. ///
public IListSubscriptionCollection Webhooks { get; } diff --git a/src/sdk/PnP.Core/Model/SharePoint/Core/Public/IListItem.cs b/src/sdk/PnP.Core/Model/SharePoint/Core/Public/IListItem.cs index 0bb981de20..32a10ca685 100644 --- a/src/sdk/PnP.Core/Model/SharePoint/Core/Public/IListItem.cs +++ b/src/sdk/PnP.Core/Model/SharePoint/Core/Public/IListItem.cs @@ -1,6 +1,7 @@ using PnP.Core.Model.Security; using PnP.Core.Services; using System; +using System.Linq; using System.Linq.Expressions; using System.Threading.Tasks; @@ -99,11 +100,17 @@ public interface IListItem : IDataModel, IDataModelGet, ID /// /// Gets a value that returns a collection of list item version objects that represent the versions of the list item + /// Implements .
+ /// See Requesting model collections + /// and IQueryable performance considerations to learn more. ///
public IListItemVersionCollection Versions { get; } /// /// Collection of attachments for this list item + /// Implements .
+ /// See Requesting model collections + /// and IQueryable performance considerations to learn more. ///
public IAttachmentCollection AttachmentFiles { get; } diff --git a/src/sdk/PnP.Core/Model/SharePoint/Core/Public/IListItemVersion.cs b/src/sdk/PnP.Core/Model/SharePoint/Core/Public/IListItemVersion.cs index bb1d6ec45f..3c3ae23a27 100644 --- a/src/sdk/PnP.Core/Model/SharePoint/Core/Public/IListItemVersion.cs +++ b/src/sdk/PnP.Core/Model/SharePoint/Core/Public/IListItemVersion.cs @@ -1,5 +1,6 @@ using PnP.Core.Model.Security; using System; +using System.Linq; namespace PnP.Core.Model.SharePoint { @@ -37,6 +38,9 @@ public interface IListItemVersion : IDataModel, IDataModelGet< /// /// Fields of this list item version. + /// Implements .
+ /// See Requesting model collections + /// and IQueryable performance considerations to learn more. ///
public IFieldCollection Fields { get; } diff --git a/src/sdk/PnP.Core/Model/SharePoint/Core/Public/IRegionalSettings.cs b/src/sdk/PnP.Core/Model/SharePoint/Core/Public/IRegionalSettings.cs index 5d96dbed9d..9d0dd4d55d 100644 --- a/src/sdk/PnP.Core/Model/SharePoint/Core/Public/IRegionalSettings.cs +++ b/src/sdk/PnP.Core/Model/SharePoint/Core/Public/IRegionalSettings.cs @@ -1,3 +1,5 @@ +using System.Linq; + namespace PnP.Core.Model.SharePoint { /// @@ -126,6 +128,9 @@ public interface IRegionalSettings : IDataModel, IDataModelGe /// /// Gets the collection of time zones used in SharePoint Online. + /// Implements .
+ /// See Requesting model collections + /// and IQueryable performance considerations to learn more. ///
public ITimeZoneCollection TimeZones { get; } diff --git a/src/sdk/PnP.Core/Model/SharePoint/Core/Public/ISecurableObject.cs b/src/sdk/PnP.Core/Model/SharePoint/Core/Public/ISecurableObject.cs index b849ea044a..0bd3937645 100644 --- a/src/sdk/PnP.Core/Model/SharePoint/Core/Public/ISecurableObject.cs +++ b/src/sdk/PnP.Core/Model/SharePoint/Core/Public/ISecurableObject.cs @@ -1,5 +1,6 @@ using PnP.Core.Model.Security; using PnP.Core.Services; +using System.Linq; using System.Threading.Tasks; namespace PnP.Core.Model.SharePoint @@ -11,6 +12,9 @@ public interface ISecurableObject { /// /// Role Assignments defined on this securable object + /// Implements .
+ /// See Requesting model collections + /// and IQueryable performance considerations to learn more. ///
public IRoleAssignmentCollection RoleAssignments { get; } diff --git a/src/sdk/PnP.Core/Model/SharePoint/Core/Public/ISite.cs b/src/sdk/PnP.Core/Model/SharePoint/Core/Public/ISite.cs index eac5b1d9e7..701072ebd9 100644 --- a/src/sdk/PnP.Core/Model/SharePoint/Core/Public/ISite.cs +++ b/src/sdk/PnP.Core/Model/SharePoint/Core/Public/ISite.cs @@ -1,6 +1,7 @@ using PnP.Core.Model.Security; using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; namespace PnP.Core.Model.SharePoint @@ -48,11 +49,17 @@ public interface ISite : IDataModel, IDataModelGet, IDataModelLoad /// /// Collection of sub-webs in the current Site object + /// Implements .
+ /// See Requesting model collections + /// and IQueryable performance considerations to learn more. ///
public IWebCollection AllWebs { get; } /// /// Collection of features enabled for the site + /// Implements .
+ /// See Requesting model collections + /// and IQueryable performance considerations to learn more. ///
public IFeatureCollection Features { get; } @@ -197,6 +204,9 @@ public interface ISite : IDataModel, IDataModelGet, IDataModelLoad /// /// Gets a value that specifies the collection of Recycle Bin items for the site collection. + /// Implements .
+ /// See Requesting model collections + /// and IQueryable performance considerations to learn more. ///
public IRecycleBinItemCollection RecycleBin { get; } @@ -247,6 +257,9 @@ public interface ISite : IDataModel, IDataModelGet, IDataModelLoad /// /// Gets a value that specifies the collection of user custom actions for the site collection. + /// Implements .
+ /// See Requesting model collections + /// and IQueryable performance considerations to learn more. ///
public IUserCustomActionCollection UserCustomActions { get; } diff --git a/src/sdk/PnP.Core/Model/SharePoint/Core/Public/IWeb.cs b/src/sdk/PnP.Core/Model/SharePoint/Core/Public/IWeb.cs index dad218628d..098f9e1437 100644 --- a/src/sdk/PnP.Core/Model/SharePoint/Core/Public/IWeb.cs +++ b/src/sdk/PnP.Core/Model/SharePoint/Core/Public/IWeb.cs @@ -2,6 +2,7 @@ using PnP.Core.Services; using System; using System.Collections.Generic; +using System.Linq; using System.Linq.Expressions; using System.Threading.Tasks; @@ -223,6 +224,9 @@ public interface IWeb : IDataModel, IDataModelGet, IDataModelLoad /// Gets the recycle bin of the website. + /// Implements .
+ /// See Requesting model collections + /// and IQueryable performance considerations to learn more. ///
public IRecycleBinItemCollection RecycleBin { get; } @@ -407,32 +411,50 @@ public interface IWeb : IDataModel, IDataModelGet, IDataModelLoad - /// Collection of lists in the current Web object + /// Collection of lists in the current Web object. + /// Implements .
+ /// See Requesting model collections + /// and IQueryable performance considerations to learn more. ///
public IListCollection Lists { get; } /// /// Collection of content types in the current Web object + /// Implements .
+ /// See Requesting model collections + /// and IQueryable performance considerations to learn more. ///
public IContentTypeCollection ContentTypes { get; } /// /// Collection of fields in the current Web object + /// Implements .
+ /// See Requesting model collections + /// and IQueryable performance considerations to learn more. ///
public IFieldCollection Fields { get; } /// /// Collection of webs in this current web + /// Implements .
+ /// See Requesting model collections + /// and IQueryable performance considerations to learn more. ///
public IWebCollection Webs { get; } /// /// Collection of features enabled for the web + /// Implements .
+ /// See Requesting model collections + /// and IQueryable performance considerations to learn more. ///
public IFeatureCollection Features { get; } /// /// Collection of folders in the current Web object + /// Implements .
+ /// See Requesting model collections + /// and IQueryable performance considerations to learn more. ///
public IFolderCollection Folders { get; } @@ -443,11 +465,17 @@ public interface IWeb : IDataModel, IDataModelGet, IDataModelLoad /// Gets the collection of all content types that apply to the current scope, including those of the current Web site, as well as any parent Web sites. + /// Implements .
+ /// See Requesting model collections + /// and IQueryable performance considerations to learn more. /// public IContentTypeCollection AvailableContentTypes { get; } /// /// Gets a value that specifies the collection of all fields available for the current scope, including those of the current site, as well as any parent sites. + /// Implements .
+ /// See Requesting model collections + /// and IQueryable performance considerations to learn more. ///
public IFieldCollection AvailableFields { get; } @@ -463,16 +491,25 @@ public interface IWeb : IDataModel, IDataModelGet, IDataModelLoad /// Gets the collection of all users that belong to the site collection. + /// Implements .
+ /// See Requesting model collections + /// and IQueryable performance considerations to learn more. /// public ISharePointUserCollection SiteUsers { get; } /// /// Gets the collection of all groups that belong to the site collection. + /// Implements .
+ /// See Requesting model collections + /// and IQueryable performance considerations to learn more. ///
public ISharePointGroupCollection SiteGroups { get; } /// /// Gets a value that specifies the collection of user custom actions for the site. + /// Implements .
+ /// See Requesting model collections + /// and IQueryable performance considerations to learn more. ///
public IUserCustomActionCollection UserCustomActions { get; } @@ -503,6 +540,9 @@ public interface IWeb : IDataModel, IDataModelGet, IDataModelLoad /// Role Definitions defined in this web + /// Implements .
+ /// See Requesting model collections + /// and IQueryable performance considerations to learn more. /// public IRoleDefinitionCollection RoleDefinitions { get; } diff --git a/src/sdk/PnP.Core/Model/SharePoint/Taxonomy/Public/ITerm.cs b/src/sdk/PnP.Core/Model/SharePoint/Taxonomy/Public/ITerm.cs index 783014b739..3229259c70 100644 --- a/src/sdk/PnP.Core/Model/SharePoint/Taxonomy/Public/ITerm.cs +++ b/src/sdk/PnP.Core/Model/SharePoint/Taxonomy/Public/ITerm.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; namespace PnP.Core.Model.SharePoint { @@ -41,6 +42,9 @@ public interface ITerm : IDataModel, IDataModelGet, IDataModelLoad /// /// Collection of child terms of this term + /// Implements .
+ /// See Requesting model collections + /// and IQueryable performance considerations to learn more. ///
public ITermCollection Terms { get; } diff --git a/src/sdk/PnP.Core/Model/SharePoint/Taxonomy/Public/ITermGroup.cs b/src/sdk/PnP.Core/Model/SharePoint/Taxonomy/Public/ITermGroup.cs index e65bc20213..67b0937a10 100644 --- a/src/sdk/PnP.Core/Model/SharePoint/Taxonomy/Public/ITermGroup.cs +++ b/src/sdk/PnP.Core/Model/SharePoint/Taxonomy/Public/ITermGroup.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; namespace PnP.Core.Model.SharePoint { @@ -35,6 +36,9 @@ public interface ITermGroup : IDataModel, IDataModelGet, /// /// Collection of term sets in this term group + /// Implements .
+ /// See Requesting model collections + /// and IQueryable performance considerations to learn more. ///
public ITermSetCollection Sets { get; } } diff --git a/src/sdk/PnP.Core/Model/SharePoint/Taxonomy/Public/ITermSet.cs b/src/sdk/PnP.Core/Model/SharePoint/Taxonomy/Public/ITermSet.cs index 693bb0a68c..6beb7cb58b 100644 --- a/src/sdk/PnP.Core/Model/SharePoint/Taxonomy/Public/ITermSet.cs +++ b/src/sdk/PnP.Core/Model/SharePoint/Taxonomy/Public/ITermSet.cs @@ -31,6 +31,9 @@ public interface ITermSet : IDataModel, IDataModelGet, IData /// /// Collection of term in this term set + /// Implements .
+ /// See Requesting model collections + /// and IQueryable performance considerations to learn more. ///
public ITermCollection Terms { get; } diff --git a/src/sdk/PnP.Core/Model/SharePoint/Taxonomy/Public/ITermStore.cs b/src/sdk/PnP.Core/Model/SharePoint/Taxonomy/Public/ITermStore.cs index 1ea6ca2f65..f09b9bc41b 100644 --- a/src/sdk/PnP.Core/Model/SharePoint/Taxonomy/Public/ITermStore.cs +++ b/src/sdk/PnP.Core/Model/SharePoint/Taxonomy/Public/ITermStore.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Linq; namespace PnP.Core.Model.SharePoint { @@ -25,6 +26,9 @@ public interface ITermStore : IDataModel, IDataModelGet, /// /// Collection of term groups in this term store + /// Implements .
+ /// See Requesting model collections + /// and IQueryable performance considerations to learn more. ///
public ITermGroupCollection Groups { get; } } diff --git a/src/sdk/PnP.Core/Model/Teams/Public/ITeam.cs b/src/sdk/PnP.Core/Model/Teams/Public/ITeam.cs index 83faef7396..8455967e40 100644 --- a/src/sdk/PnP.Core/Model/Teams/Public/ITeam.cs +++ b/src/sdk/PnP.Core/Model/Teams/Public/ITeam.cs @@ -1,5 +1,6 @@ using PnP.Core.Model.Security; using System; +using System.Linq; using System.Threading.Tasks; namespace PnP.Core.Model.Teams @@ -92,21 +93,33 @@ public interface ITeam : IDataModel, IDataModelGet, IDataModelLoad /// /// Collection of channels in this current Team + /// Implements .
+ /// See Requesting model collections + /// and IQueryable performance considerations to learn more. ///
public ITeamChannelCollection Channels { get; } /// /// Collection of installed apps in this current Team + /// Implements .
+ /// See Requesting model collections + /// and IQueryable performance considerations to learn more. ///
public ITeamAppCollection InstalledApps { get; } /// /// Collection of Owners of the current Team + /// Implements .
+ /// See Requesting model collections + /// and IQueryable performance considerations to learn more. ///
public IGraphUserCollection Owners { get; } /// /// Collection of Members of the current Team + /// Implements .
+ /// See Requesting model collections + /// and IQueryable performance considerations to learn more. ///
public IGraphUserCollection Members { get; } diff --git a/src/sdk/PnP.Core/Model/Teams/Public/ITeamChannel.cs b/src/sdk/PnP.Core/Model/Teams/Public/ITeamChannel.cs index 515fd50f26..9853e2ce55 100644 --- a/src/sdk/PnP.Core/Model/Teams/Public/ITeamChannel.cs +++ b/src/sdk/PnP.Core/Model/Teams/Public/ITeamChannel.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; namespace PnP.Core.Model.Teams { @@ -45,11 +46,17 @@ public interface ITeamChannel : IDataModel, IDataModelGet /// Tabs in this Channel + /// Implements .
+ /// See Requesting model collections + /// and IQueryable performance considerations to learn more. /// public ITeamChannelTabCollection Tabs { get; } /// /// Messages in this Team Channel + /// Implements .
+ /// See Requesting model collections + /// and IQueryable performance considerations to learn more. ///
public ITeamChatMessageCollection Messages { get; } }