You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
<p>First, inject the <codeclass="language-text">IDataLoaderContextAccessor</code> into your GraphQL type class.</p>
104
104
<p>Then use the <codeclass="language-text">Context</code> property on the accessor to get the current <codeclass="language-text">DataLoaderContext</code>. The <codeclass="language-text">DataLoaderDocumentListener</code> configured above ensures that each request will have its own context instance.</p>
105
-
<p>Use one of the "GetOrAddLoader" methods on the <codeclass="language-text">DataLoaderContext</code>. These methods all require a string key to uniquely identify each loader. They also require a delegate for fetching the data. Each method will get an existing loader or add a new one, identified by the string key. Each method has various overloads to support different ways to load and map data with the keys.</p>
105
+
<p>Use one of the <codeclass="language-text">GetOrAdd*Loader</code> methods on the <codeclass="language-text">DataLoaderContext</code>. These methods all require a string key to uniquely identify each loader. They also require a delegate for fetching the data. Each method will get an existing loader or add a new one, identified by the string key. Each method has various overloads to support different ways to load and map data with the keys.</p>
106
106
<p>Call <codeclass="language-text">LoadAsync()</code> on the data loader. This will queue the request and return a <codeclass="language-text">IDataLoaderResult<T></code>. If the result has already been cached, the returned value will be pulled from the cache.</p>
107
107
<p>The <codeclass="language-text">ExecutionStrategy</code> will dispatch queued data loaders after all other pending fields have been resolved.</p>
108
108
<p>If your code requires an asynchronous call prior to queuing the data loader, use the <codeclass="language-text">ResolveAsync</code> field builder method to return a
@@ -113,8 +113,26 @@ <h2 id="usage" style="position:relative;"><a href="#usage" aria-label="usage per
113
113
method of the returned <codeclass="language-text">IDataLoaderResult<T></code>. You can use a synchronous or asynchronous delegate, and it can return another
114
114
<codeclass="language-text">IDataLoaderResult<T></code> if you wish to chain dataloaders together. This may result in the field builder's Resolve delegate
115
115
signature looking like <codeclass="language-text">IDataLoaderResult<IDataLoaderResult<T>></code>, which is correct and will be handled properly by the execution strategy.</p>
<p>The decision about whether to use the <codeclass="language-text">GetOrAddBatchLoader</code> or <codeclass="language-text">GetOrAddCollectionBatchLoader</code> method should be based on whether each key can link to only one or to multiple values:</p>
118
+
<ul>
119
+
<li>use <codeclass="language-text">GetOrAddBatchLoader</code> for one-to-one or many-to-one relationships, i.e. when each key links to a single value; think for example of resolving the user who made an order: each order maps to one (and only one) user;</li>
120
+
<li>use <codeclass="language-text">GetOrAddCollectionBatchLoader</code> for one-to-many or many-to-many relationships, i.e. when each key links to multiple values; think for example of resolving orders for a user: each user may map to (zero or) more orders.</li>
121
+
</ul>
122
+
<p>Note that what matters here is the cardinality of the relation as seen from the resolver's perspective. Think for example of orders and products. In theory, a product can appear in multiple orders and an order can contain multiple products, so this is a many-to-many relationship. However, a resolver for <codeclass="language-text">Product.Orders</code> (or alternatively, <codeclass="language-text">Order.Products</code>) will only need to care for the one-to-many side of the relation, and thus use the <codeclass="language-text">GetOrAddBatchCollectionLoader</code>.</p>
123
+
<p>The same applies to one-to-many (or many-to-one) relationships. A resolver on the "one" side of the relation will need to use <codeclass="language-text">GetOrAddBatchCollectionLoader</code>, while a resolver on the "many" side will need to use <codeclass="language-text">GetOrAddBatchLoader</code>.</p>
<p>This is an example of using a DataLoader to batch requests for loading items by a key. <codeclass="language-text">LoadAsync()</code> is called by the field resolver for each Order. <codeclass="language-text">IUsersStore.GetUsersByIdAsync()</code> will be called with the batch of userIds that were requested.</p>
125
+
<p>Below are some example implementations of a DataLoader for different use cases given the following schema:</p>
<p>This is an example of using a DataLoader to batch requests for loading a single item by a key. Since each order belongs to exactly one user, from the perspective of an order this is a one-to-one relationship, so we should use <codeclass="language-text">GetOrAddBatchLoader</code>.</p>
135
+
<p>Below, <codeclass="language-text">LoadAsync()</code> is called by the field resolver for each Order. <codeclass="language-text">IUsersStore.GetUsersByIdAsync()</code> will be called with the batch of userIds that were requested.</p>
<spanclass="token class-name"><spanclass="token keyword">var</span></span> users <spanclass="token operator">=</span><spanclass="token keyword">await</span><spanclass="token range operator">..</span><spanclass="token punctuation">.</span><spanclass="token comment">// load data from database</span>
<p>This is an example of using a DataLoader to batch requests for loading a collection of items by a key. This is used when a key may be associated with more than one item. <codeclass="language-text">LoadAsync()</code> is called by the field resolver for each User. A User can have zero to many Orders. <codeclass="language-text">IOrdersStore.GetOrdersByUserIdAsync</code> will be called with a batch of userIds that have been requested.</p>
<p>This is an example of using a DataLoader to batch requests for loading a collection of items by a key. This is used when a key may be associated with more than one item. Since each user can have (zero or) more orders, from the perspective of a user this is a one-to-many relationship, so we should use <codeclass="language-text">GetOrAddCollectionBatchLoader</code>.</p>
174
+
<p><codeclass="language-text">LoadAsync()</code> is called by the field resolver for each User. <codeclass="language-text">IOrdersStore.GetOrdersByUserIdAsync</code> will be called with a batch of userIds that have been requested.</p>
<p>This is an example of using a DataLoader without batching. This could be useful if the data may be requested multiple times. The result will be cached the first time. Subsequent calls to <codeclass="language-text">LoadAsync()</code> will return the cached result.</p>
<p>This is an example of using two chained DataLoaders to batch requests together, with asynchronous code before the data loaders execute, and post-processing afterwards.</p>
0 commit comments