diff --git a/cSpell.json b/cSpell.json index b7050301b3a..17ed560b53f 100644 --- a/cSpell.json +++ b/cSpell.json @@ -43,7 +43,9 @@ "meros", "Structs", "reencode", - "WunderGraph" + "WunderGraph", + "CCPA", + "decompile" ], "ignoreWords": [ "Badurina", diff --git a/src/CookieCrumble/src/CookieCrumble/Extensions/SnapshotExtensions.cs b/src/CookieCrumble/src/CookieCrumble/Extensions/SnapshotExtensions.cs index 0e12a4c1da4..e46ff7ef232 100644 --- a/src/CookieCrumble/src/CookieCrumble/Extensions/SnapshotExtensions.cs +++ b/src/CookieCrumble/src/CookieCrumble/Extensions/SnapshotExtensions.cs @@ -23,6 +23,13 @@ public static void MatchSnapshot( ISnapshotValueFormatter? formatter = null) => Snapshot.Match(value, postFix?.ToString(), extension, formatter); + public static void MatchMarkdownSnapshot( + this object? value, + object? postFix = null, + string? extension = null, + ISnapshotValueFormatter? formatter = null) + => Snapshot.Create(postFix?.ToString(), extension).Add(value, formatter: formatter).MatchMarkdown(); + public static void MatchSnapshot( this ISyntaxNode? value, string? postFix = null) diff --git a/src/CookieCrumble/src/CookieCrumble/Formatters/JsonSnapshotValueFormatter.cs b/src/CookieCrumble/src/CookieCrumble/Formatters/JsonSnapshotValueFormatter.cs index 791f93a2a5d..81285d8fe49 100644 --- a/src/CookieCrumble/src/CookieCrumble/Formatters/JsonSnapshotValueFormatter.cs +++ b/src/CookieCrumble/src/CookieCrumble/Formatters/JsonSnapshotValueFormatter.cs @@ -6,7 +6,7 @@ namespace CookieCrumble.Formatters; -internal sealed class JsonSnapshotValueFormatter : ISnapshotValueFormatter +internal sealed class JsonSnapshotValueFormatter : ISnapshotValueFormatter, IMarkdownSnapshotValueFormatter { private static readonly JsonSerializerSettings _settings = new() @@ -22,9 +22,19 @@ internal sealed class JsonSnapshotValueFormatter : ISnapshotValueFormatter public bool CanHandle(object? value) => true; - + public void Format(IBufferWriter snapshot, object? value) => snapshot.Append(JsonConvert.SerializeObject(value, _settings)); + + public void FormatMarkdown(IBufferWriter snapshot, object? value) + { + snapshot.Append("```json"); + snapshot.AppendLine(); + Format(snapshot, value); + snapshot.AppendLine(); + snapshot.Append("```"); + snapshot.AppendLine(); + } private class ChildFirstContractResolver : DefaultContractResolver { diff --git a/src/HotChocolate/Data/Directory.Build.props b/src/HotChocolate/Data/Directory.Build.props index cd676459498..6a85a251082 100644 --- a/src/HotChocolate/Data/Directory.Build.props +++ b/src/HotChocolate/Data/Directory.Build.props @@ -8,6 +8,8 @@ $(WarningsAsErrors);nullable true en + enable + diff --git a/src/HotChocolate/Data/HotChocolate.Data.sln b/src/HotChocolate/Data/HotChocolate.Data.sln index 86ef6f21cc0..77eb1000c34 100644 --- a/src/HotChocolate/Data/HotChocolate.Data.sln +++ b/src/HotChocolate/Data/HotChocolate.Data.sln @@ -85,6 +85,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HotChocolate.Data.AutoMappe EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HotChocolate.AspNetCore.Tests.Utilities", "..\AspNetCore\test\AspNetCore.Tests.Utilities\HotChocolate.AspNetCore.Tests.Utilities.csproj", "{AB5D66E9-FA86-4AAE-910A-BEEC1C4B8A80}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HotChocolate.Data.EntityFramework.Helpers", "src\EntityFramework.Helpers\HotChocolate.Data.EntityFramework.Helpers.csproj", "{F781C048-BCA9-4560-B796-4E892088E1BA}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -133,6 +135,7 @@ Global {0AB70663-9D52-4415-B265-0D1F001D7576} = {91887A91-7B1C-4287-A1E0-BD4E0DAF24C7} {F793AC13-0500-492A-914D-4229F6AE0687} = {4EE990B2-C327-46DA-8FE8-F95AC228E47F} {AB5D66E9-FA86-4AAE-910A-BEEC1C4B8A80} = {882EC02D-5E1D-41F5-AD9F-AA06E31D133A} + {F781C048-BCA9-4560-B796-4E892088E1BA} = {91887A91-7B1C-4287-A1E0-BD4E0DAF24C7} EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {D68A0AB9-871A-487B-8D12-1A7544D81B9E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU @@ -545,5 +548,17 @@ Global {AB5D66E9-FA86-4AAE-910A-BEEC1C4B8A80}.Release|x64.Build.0 = Release|Any CPU {AB5D66E9-FA86-4AAE-910A-BEEC1C4B8A80}.Release|x86.ActiveCfg = Release|Any CPU {AB5D66E9-FA86-4AAE-910A-BEEC1C4B8A80}.Release|x86.Build.0 = Release|Any CPU + {F781C048-BCA9-4560-B796-4E892088E1BA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F781C048-BCA9-4560-B796-4E892088E1BA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F781C048-BCA9-4560-B796-4E892088E1BA}.Debug|x64.ActiveCfg = Debug|Any CPU + {F781C048-BCA9-4560-B796-4E892088E1BA}.Debug|x64.Build.0 = Debug|Any CPU + {F781C048-BCA9-4560-B796-4E892088E1BA}.Debug|x86.ActiveCfg = Debug|Any CPU + {F781C048-BCA9-4560-B796-4E892088E1BA}.Debug|x86.Build.0 = Debug|Any CPU + {F781C048-BCA9-4560-B796-4E892088E1BA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F781C048-BCA9-4560-B796-4E892088E1BA}.Release|Any CPU.Build.0 = Release|Any CPU + {F781C048-BCA9-4560-B796-4E892088E1BA}.Release|x64.ActiveCfg = Release|Any CPU + {F781C048-BCA9-4560-B796-4E892088E1BA}.Release|x64.Build.0 = Release|Any CPU + {F781C048-BCA9-4560-B796-4E892088E1BA}.Release|x86.ActiveCfg = Release|Any CPU + {F781C048-BCA9-4560-B796-4E892088E1BA}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/src/HotChocolate/Data/src/EntityFramework.Helpers/HotChocolate.Data.EntityFramework.Helpers.csproj b/src/HotChocolate/Data/src/EntityFramework.Helpers/HotChocolate.Data.EntityFramework.Helpers.csproj new file mode 100644 index 00000000000..e73cdbf4b99 --- /dev/null +++ b/src/HotChocolate/Data/src/EntityFramework.Helpers/HotChocolate.Data.EntityFramework.Helpers.csproj @@ -0,0 +1,31 @@ + + + + HotChocolate.Data.EntityFramework.Helpers + HotChocolate.Data.EntityFramework.Helpers + HotChocolate.Data + Provides helper classes to implement cursor paging in a layerd architecture without the need to reference HotChocolate GraphQL libraries. + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/HotChocolate/Data/src/EntityFramework.Helpers/Paging/BatchQueryRewriter.cs b/src/HotChocolate/Data/src/EntityFramework.Helpers/Paging/BatchQueryRewriter.cs new file mode 100644 index 00000000000..5867dd347d6 --- /dev/null +++ b/src/HotChocolate/Data/src/EntityFramework.Helpers/Paging/BatchQueryRewriter.cs @@ -0,0 +1,169 @@ +using System.Diagnostics.CodeAnalysis; +using System.Linq.Expressions; +using System.Reflection; + +namespace HotChocolate.Data; + +internal sealed class BatchQueryRewriter(PagingArguments arguments) : ExpressionVisitor +{ + private PropertyInfo? _resultProperty; + private DataSetKey[]? _keys; + + public PropertyInfo ResultProperty => _resultProperty ?? throw new InvalidOperationException(); + + public DataSetKey[] Keys => _keys ?? throw new InvalidOperationException(); + + protected override Expression VisitExtension(Expression node) + => node.CanReduce + ? base.VisitExtension(node) + : node; + + protected override Expression VisitMethodCall(MethodCallExpression node) + { + if (IsInclude(node) && TryExtractProperty(node, out var property) && _resultProperty is null) + { + _resultProperty = property; + var newIncludeExpression = RewriteInclude(node, property); + return base.VisitMethodCall(newIncludeExpression); + } + + return base.VisitMethodCall(node); + } + + private MethodCallExpression RewriteInclude(MethodCallExpression node, PropertyInfo property) + { + var forward = arguments.Last is null; + + var entityType = node.Arguments[0].Type.GetGenericArguments()[0]; + var includeType = property.PropertyType.GetGenericArguments()[0]; + var lambda = (LambdaExpression)((UnaryExpression)node.Arguments[1]).Operand; + + var parser = new DataSetKeyParser(); + parser.Visit(lambda); + var keys = _keys = parser.Keys.ToArray(); + + var pagingExpr = ApplyPaging(lambda.Body, arguments, keys, forward); + var newLambda = Expression.Lambda(pagingExpr, lambda.Parameters); + return Expression.Call(null, Include(), node.Arguments[0], Expression.Constant(newLambda)); + + MethodInfo Include() + => typeof(EntityFrameworkQueryableExtensions) + .GetMethods(BindingFlags.Public | BindingFlags.Static) + .First(t => t.Name.Equals("Include") && t.GetGenericArguments().Length == 2) + .MakeGenericMethod(entityType, typeof(IEnumerable<>).MakeGenericType(includeType)); + } + + private static Expression ApplyPaging( + Expression enumerable, + PagingArguments pagingArgs, + DataSetKey[] keys, + bool forward) + { + MethodInfo? where = null; + MethodInfo? take = null; + + if (pagingArgs.After is not null) + { + var cursor = CursorParser.Parse(pagingArgs.After, keys); + enumerable = Expression.Call( + null, + Where(), + enumerable, + PagingQueryableExtensions.BuildWhereExpression(keys, cursor, forward)); + } + + if (pagingArgs.Before is not null) + { + var cursor = CursorParser.Parse(pagingArgs.Before, keys); + enumerable = Expression.Call( + null, + Where(), + enumerable, + PagingQueryableExtensions.BuildWhereExpression(keys, cursor, forward)); + } + + if (pagingArgs.First is not null) + { + var first = Expression.Constant(pagingArgs.First.Value); + enumerable = Expression.Call(null, Take(), enumerable, first); + } + + if (pagingArgs.Last is not null) + { + var last = Expression.Constant(pagingArgs.Last.Value); + enumerable = Expression.Call(null, Take(), enumerable, last); + } + + return enumerable; + + MethodInfo Where() + => where ??= typeof(Enumerable) + .GetMethods(BindingFlags.Public | BindingFlags.Static) + .First(t => t.Name.Equals("Where") && t.GetGenericArguments().Length == 1) + .MakeGenericMethod(typeof(T)); + + MethodInfo Take() + => take ??= typeof(Enumerable) + .GetMethods(BindingFlags.Public | BindingFlags.Static) + .First(t => t.Name.Equals("Take") && t.GetGenericArguments().Length == 1) + .MakeGenericMethod(typeof(T)); + } + + private static bool IsInclude(MethodCallExpression node) + => IsMethod(node, nameof(EntityFrameworkQueryableExtensions.Include)); + + private static bool IsMethod(MethodCallExpression node, string name) + => node.Method.DeclaringType == typeof(EntityFrameworkQueryableExtensions) && + node.Method.Name.Equals(name, StringComparison.Ordinal); + + private static bool TryExtractProperty( + MethodCallExpression node, + [NotNullWhen(true)] out PropertyInfo? property) + { + if (node.Arguments is [_, UnaryExpression { Operand: LambdaExpression l }]) + { + return TryExtractProperty1(l.Body, out property); + } + + property = null; + return false; + } + + private static bool TryExtractProperty1(Expression expression, out PropertyInfo? property) + { + property = null; + + switch (expression) + { + case MemberExpression memberExpression: + property = memberExpression.Member as PropertyInfo; + return property != null; + + case MethodCallExpression methodCallExpression: + { + if (methodCallExpression.Arguments.Count > 0) + { + var firstArgument = methodCallExpression.Arguments[0]; + + switch (firstArgument) + { + case MethodCallExpression: + return TryExtractProperty1(firstArgument, out property); + + case UnaryExpression unaryExpression: + return TryExtractProperty1(unaryExpression.Operand, out property); + + case MemberExpression: + return TryExtractProperty1(firstArgument, out property); + } + } + break; + } + + case UnaryExpression unaryExpression: + return TryExtractProperty1(unaryExpression.Operand, out property); + } + + return false; + } +} diff --git a/src/HotChocolate/Data/src/EntityFramework.Helpers/Paging/CursorFormatter.cs b/src/HotChocolate/Data/src/EntityFramework.Helpers/Paging/CursorFormatter.cs new file mode 100644 index 00000000000..9d32bc4619c --- /dev/null +++ b/src/HotChocolate/Data/src/EntityFramework.Helpers/Paging/CursorFormatter.cs @@ -0,0 +1,104 @@ +using System.Buffers; +using System.Buffers.Text; +using System.Text; + +namespace HotChocolate.Data; + +internal static class CursorFormatter +{ + public static string Format(T item, DataSetKey[] keys) + { + if (item == null) + { + throw new ArgumentNullException(nameof(item)); + } + + if (keys == null) + { + throw new ArgumentNullException(nameof(keys)); + } + + if (keys.Length == 0) + { + throw new ArgumentException("The number of keys must be greater than zero.", nameof(keys)); + } + + Span span = stackalloc byte[256]; + byte[]? poolArray = null; + + var totalWritten = 0; + var first = true; + + foreach (var key in keys) + { + if (!first) + { + if (totalWritten + 1 > span.Length) + { + ExpandBuffer(ref poolArray, ref span, totalWritten, 1); + } + span[totalWritten++] = (byte)':'; + } + else + { + first = false; + } + + if (!key.TryFormat(item, span[totalWritten..], out var written)) + { + ExpandBuffer(ref poolArray, ref span, totalWritten, written); + + if (!key.TryFormat(item, span[totalWritten..], out written)) + { + throw new InvalidOperationException(); + } + } + totalWritten += written; + } + + var maxNeededSpace = Base64.GetMaxEncodedToUtf8Length(totalWritten); + + if (maxNeededSpace > span.Length) + { + ExpandBuffer(ref poolArray, ref span, totalWritten, maxNeededSpace - totalWritten); + } + + if (Base64.EncodeToUtf8InPlace(span, totalWritten, out var bytesWritten) != OperationStatus.Done) + { + throw new InvalidOperationException("The input is not a valid UTF-8 string."); + } + + var result = Encoding.UTF8.GetString(span.Slice(0, bytesWritten)); + + if (poolArray != null) + { + ArrayPool.Shared.Return(poolArray); + } + + return result; + } + + private static void ExpandBuffer( + ref byte[]? poolArray, + ref Span span, + int currentLength, + int additionalLength) + { + var newSize = poolArray == null ? 256 : poolArray.Length * 2; + while (newSize < currentLength + additionalLength) + { + newSize *= 2; + } + + var newPoolArray = ArrayPool.Shared.Rent(newSize); + span[..currentLength].CopyTo(newPoolArray); + + if (poolArray != null) + { + ArrayPool.Shared.Return(poolArray); + } + + poolArray = newPoolArray; + span = new Span(poolArray); + } +} \ No newline at end of file diff --git a/src/HotChocolate/Data/src/EntityFramework.Helpers/Paging/CursorParser.cs b/src/HotChocolate/Data/src/EntityFramework.Helpers/Paging/CursorParser.cs new file mode 100644 index 00000000000..3fa4c8fc693 --- /dev/null +++ b/src/HotChocolate/Data/src/EntityFramework.Helpers/Paging/CursorParser.cs @@ -0,0 +1,66 @@ +using System.Buffers; +using System.Buffers.Text; +using System.Text; + +namespace HotChocolate.Data; + +internal static class CursorParser +{ + private const byte _separator = (byte)':'; + + public static object[] Parse(string cursor, ReadOnlySpan keys) + { + if (cursor == null) + { + throw new ArgumentNullException(nameof(cursor)); + } + + if (keys.Length == 0) + { + throw new ArgumentException("The number of keys must be greater than zero.", nameof(keys)); + } + + var buffer = ArrayPool.Shared.Rent(cursor.Length * 4); + var bufferSpan = buffer.AsSpan(); + var length = Encoding.UTF8.GetBytes(cursor, bufferSpan); + Base64.DecodeFromUtf8InPlace(bufferSpan[..length], out var written); + + if (bufferSpan.Length > written) + { + bufferSpan = bufferSpan[..written]; + } + + var key = 0; + var start = 0; + var end = 0; + var parsedCursor = new object[keys.Length]; + for(var current = 0; current < bufferSpan.Length; current++) + { + var code = bufferSpan[current]; + end++; + + if (code == _separator || current == bufferSpan.Length - 1) + { + if (key >= keys.Length) + { + ArrayPool.Shared.Return(buffer); + throw new ArgumentException("The number of keys must match the number of values.", nameof(cursor)); + } + + if (code == _separator) + { + end--; + } + + var span = bufferSpan.Slice(start, end); + parsedCursor[key] = keys[key].Parse(span); + start = current + 1; + end = 0; + key++; + } + } + + ArrayPool.Shared.Return(buffer); + return parsedCursor; + } +} \ No newline at end of file diff --git a/src/HotChocolate/Data/src/EntityFramework.Helpers/Paging/DataSetKey.cs b/src/HotChocolate/Data/src/EntityFramework.Helpers/Paging/DataSetKey.cs new file mode 100644 index 00000000000..0b44b4d1b68 --- /dev/null +++ b/src/HotChocolate/Data/src/EntityFramework.Helpers/Paging/DataSetKey.cs @@ -0,0 +1,127 @@ +using System.Buffers.Text; +using System.Reflection; +using System.Text; + +namespace HotChocolate.Data; + +internal sealed class DataSetKey +{ + public DataSetKey(PropertyInfo property, bool ascending = true) + { + Property = property; + CompareMethod = Property.PropertyType.GetMethod("CompareTo", [Property.PropertyType,])!; + Ascending = ascending; + } + + public bool Ascending { get; set; } + + public PropertyInfo Property { get; } + + public MethodInfo CompareMethod { get; } + + public object Parse(string cursorValue) + { + if (typeof(string) == Property.PropertyType) + { + return cursorValue; + } + + if (typeof(int) == Property.PropertyType) + { + return int.Parse(cursorValue); + } + + throw new NotSupportedException(); + } + + public object Parse(ReadOnlySpan cursorValue) + { + if (typeof(string) == Property.PropertyType) + { + return Encoding.UTF8.GetString(cursorValue); + } + + if (typeof(short) == Property.PropertyType) + { + if (!Utf8Parser.TryParse(cursorValue, out short value, out _)) + { + throw new FormatException("The cursor value is not a valid short."); + } + + return value; + } + + if (typeof(int) == Property.PropertyType) + { + if (!Utf8Parser.TryParse(cursorValue, out int value, out _)) + { + throw new FormatException("The cursor value is not a valid integer."); + } + + return value; + } + + if (typeof(long) == Property.PropertyType) + { + if (!Utf8Parser.TryParse(cursorValue, out long value, out _)) + { + throw new FormatException("The cursor value is not a valid long."); + } + + return value; + } + + + if (typeof(Guid) == Property.PropertyType) + { + if (!Utf8Parser.TryParse(cursorValue, out Guid value, out _)) + { + throw new FormatException("The cursor value is not a valid guid."); + } + + return value; + } + + throw new NotSupportedException(); + } + + public bool TryFormat(object instance, Span span, out int written) + { + if (typeof(string) == Property.PropertyType) + { + var data = ((string)Property.GetValue(instance)!).AsSpan(); +#if NET8_0_OR_GREATER + return Encoding.UTF8.TryGetBytes(data, span, out written); +#else + written = Encoding.UTF8.GetBytes(data, span); + return true; +#endif + } + + if (typeof(short) == Property.PropertyType) + { + var data = (short)Property.GetValue(instance)!; + return Utf8Formatter.TryFormat(data, span, out written); + } + + if (typeof(int) == Property.PropertyType) + { + var data = (int)Property.GetValue(instance)!; + return Utf8Formatter.TryFormat(data, span, out written); + } + + if (typeof(long) == Property.PropertyType) + { + var data = (long)Property.GetValue(instance)!; + return Utf8Formatter.TryFormat(data, span, out written); + } + + if (typeof(Guid) == Property.PropertyType) + { + var data = (Guid)Property.GetValue(instance)!; + return Utf8Formatter.TryFormat(data, span, out written); + } + + throw new NotSupportedException(); + } +} \ No newline at end of file diff --git a/src/HotChocolate/Data/src/EntityFramework.Helpers/Paging/DataSetKeyParser.cs b/src/HotChocolate/Data/src/EntityFramework.Helpers/Paging/DataSetKeyParser.cs new file mode 100644 index 00000000000..e981e418b46 --- /dev/null +++ b/src/HotChocolate/Data/src/EntityFramework.Helpers/Paging/DataSetKeyParser.cs @@ -0,0 +1,92 @@ +using System.Diagnostics.CodeAnalysis; +using System.Linq.Expressions; +using System.Reflection; + +namespace HotChocolate.Data; + +internal sealed class DataSetKeyParser : ExpressionVisitor +{ + private readonly List _keys = new(); + + public IReadOnlyList Keys => _keys; + + protected override Expression VisitExtension(Expression node) + => node.CanReduce ? base.VisitExtension(node) : node; + + protected override Expression VisitMethodCall(MethodCallExpression node) + { + if (IsOrderBy(node)) + { + PushProperty(node); + } + else if (IsThenBy(node)) + { + PushProperty(node); + } + else if (IsOrderByDescending(node)) + { + PushProperty(node, false); + } + else if (IsThenByDescending(node)) + { + PushProperty(node, false); + } + + return base.VisitMethodCall(node); + } + + private static bool IsOrderBy(MethodCallExpression node) + => IsMethod(node, nameof(Queryable.OrderBy), typeof(Queryable)) || + IsMethod(node, nameof(Enumerable.OrderBy), typeof(Enumerable)); + + private static bool IsThenBy(MethodCallExpression node) + => IsMethod(node, nameof(Queryable.ThenBy), typeof(Queryable)) || + IsMethod(node, nameof(Enumerable.ThenBy), typeof(Enumerable)); + + private static bool IsOrderByDescending(MethodCallExpression node) + => IsMethod(node, nameof(Queryable.OrderByDescending), typeof(Queryable)) || + IsMethod(node, nameof(Enumerable.OrderByDescending), typeof(Enumerable)); + + private static bool IsThenByDescending(MethodCallExpression node) + => IsMethod(node, nameof(Queryable.ThenByDescending), typeof(Queryable)) || + IsMethod(node, nameof(Enumerable.ThenByDescending), typeof(Enumerable)); + + private static bool IsMethod(MethodCallExpression node, string name, Type declaringType) + => node.Method.DeclaringType == declaringType && + node.Method.Name.Equals(name, StringComparison.Ordinal); + + private void PushProperty(MethodCallExpression node, bool ascending = true) + { + if (TryExtractProperty(node, out var property)) + { + _keys.Insert(0, new DataSetKey(property, ascending)); + } + } + + private static bool TryExtractProperty( + MethodCallExpression node, + [NotNullWhen(true)] out PropertyInfo? property) + { + if (node.Arguments.Count == 2 && + node.Arguments[1] is UnaryExpression u && + u.Operand is LambdaExpression l && + l.Body is MemberExpression m && + m.Member is PropertyInfo p) + { + property = p; + return true; + } + + if (node.Arguments.Count == 2 && + node.Arguments[1] is LambdaExpression l1 && + l1.Body is MemberExpression m1 && + m1.Member is PropertyInfo p1) + { + property = p1; + return true; + } + + property = null; + return false; + } +} \ No newline at end of file diff --git a/src/HotChocolate/Data/src/EntityFramework.Helpers/Paging/Extensions/PagingQueryableExtensions.cs b/src/HotChocolate/Data/src/EntityFramework.Helpers/Paging/Extensions/PagingQueryableExtensions.cs new file mode 100644 index 00000000000..01f1c652af0 --- /dev/null +++ b/src/HotChocolate/Data/src/EntityFramework.Helpers/Paging/Extensions/PagingQueryableExtensions.cs @@ -0,0 +1,289 @@ +using System.Collections.Concurrent; +using System.Linq.Expressions; +using System.Reflection; +using Microsoft.EntityFrameworkCore.Query; + +namespace HotChocolate.Data; + +/// +/// Provides extension methods to page a queryable. +/// +public static class PagingQueryableExtensions +{ + private static readonly MethodInfo _createAndConvert = typeof(PagingQueryableExtensions) + .GetMethod(nameof(CreateAndConvertParameter), BindingFlags.NonPublic | BindingFlags.Static)!; + private static readonly ConcurrentDictionary> _cachedConverters = new(); + + /// + /// Executes a query with paging and returns the selected page. + /// + /// + /// The queryable to be paged. + /// + /// + /// The paging arguments. + /// + /// + /// The cancellation token. + /// + /// + /// The type of the items in the queryable. + /// + /// + /// Returns a page of items. + /// + /// + /// If the queryable does not have any keys specified. + /// + public static async ValueTask> ToPageAsync( + this IQueryable source, + PagingArguments arguments, + CancellationToken cancellationToken = default) + { + var keys = ParseDataSetKeys(source); + + if(keys.Length == 0) + { + throw new ArgumentException( + "In order to use cursor pagination, you must specify at least on key using the `OrderBy` method.", + nameof(source)); + } + + if(arguments.Last is not null && arguments.First is not null) + { + throw new ArgumentException( + "You can specify either `first` or `last`, but not both as this can lead to unpredictable results.", + nameof(arguments)); + } + + var forward = arguments.Last is null; + + if (arguments.After is not null) + { + var cursor = CursorParser.Parse(arguments.After, keys); + source = source.Where(BuildWhereExpression(keys, cursor, forward)); + } + + if (arguments.Before is not null) + { + var cursor = CursorParser.Parse(arguments.Before, keys); + source = source.Where(BuildWhereExpression(keys, cursor, forward)); + } + + if (arguments.First is not null) + { + source = source.Take(arguments.First.Value); + } + + if (arguments.Last is not null) + { + source = source.Reverse().Take(arguments.Last.Value); + } + + var result = await source.ToListAsync(cancellationToken); + + if(result.Count == 0) + { + return Page.Empty; + } + + if (!forward) + { + result.Reverse(); + } + + return CreatePage(result, arguments, keys); + } + + /// + /// Executes a batch query with paging and returns the selected pages for each parent. + /// + /// + /// The queryable to be paged. + /// + /// + /// A function to select the key of the parent. + /// + /// + /// The paging arguments. + /// + /// + /// The cancellation token. + /// + /// + /// The type of the items in the queryable. + /// + /// + /// The type of the parent key. + /// + /// + /// The type of the property that is being paged. + /// + /// + /// Returns a dictionary of pages for each parent. + /// + /// + /// If the result is not a list or an enumerable. + /// + public static async ValueTask, Page>> ToBatchPageAsync( + this IIncludableQueryable> source, + Func keySelector, + PagingArguments arguments, + CancellationToken cancellationToken = default) + where TKey : notnull + { + var rewriter = new BatchQueryRewriter(arguments); + var expression = rewriter.Visit(source.Expression); + var list = await source.Provider.CreateQuery(expression).ToListAsync(cancellationToken); + var result = new Dictionary, Page>(); + + foreach (var group in list) + { + var key = new PageKey(keySelector(group), arguments); + + switch (rewriter.ResultProperty.GetValue(group)) + { + case IReadOnlyList resultList: + result.Add(key, CreatePage(resultList, arguments, rewriter.Keys)); + break; + + case IEnumerable resultEnumerable: + result.Add(key, CreatePage(resultEnumerable.ToArray(), arguments, rewriter.Keys)); + break; + + default: + throw new InvalidOperationException( + "The result must be a list or an enumerable."); + } + } + + return result; + } + + private static Page CreatePage(IReadOnlyList items, PagingArguments arguments, DataSetKey[] keys) + { + var hasPrevious = arguments.First is not null && items.Count > 0 || + arguments.Last is not null && items.Count > arguments.Last; + var hasNext = arguments.First is not null && items.Count > arguments.First || + arguments.Last is not null && items.Count > 0; + + return new Page(items, hasNext, hasPrevious, item => CursorFormatter.Format(item, keys)); + } + + private static DataSetKey[] ParseDataSetKeys(IQueryable source) + { + var parser = new DataSetKeyParser(); + parser.Visit(source.Expression); + return parser.Keys.ToArray(); + } + + internal static Expression> BuildWhereExpression( + DataSetKey[] keys, + object[] cursor, + bool forward) + { + if (keys == null) + { + throw new ArgumentNullException(nameof(keys)); + } + + if (cursor == null) + { + throw new ArgumentNullException(nameof(cursor)); + } + + if (keys.Length == 0) + { + throw new ArgumentException("At least one key must be specified.", nameof(keys)); + } + + if (keys.Length != cursor.Length) + { + throw new ArgumentException("The number of keys must match the number of values.", nameof(cursor)); + } + + var cursorExpr = new Expression[cursor.Length]; + for (var i = 0; i < cursor.Length; i++) + { + cursorExpr[i] = CreateParameter(cursor[i], keys[i].Property.PropertyType); + } + + var handled = new List(); + Expression? expression = null; + + var entity = Expression.Parameter(typeof(T), "t"); + var zero = Expression.Constant(0); + + for (var i = 0; i < keys.Length; i++) + { + var key = keys[i]; + Expression? current = null; + Expression keyExpr; + + for (var j = 0; j < handled.Count; j++) + { + var handledKey = handled[j]; + + keyExpr = + Expression.Equal( + Expression.Call( + Expression.Property(entity, handledKey.Property), + handledKey.CompareMethod, + cursorExpr[j]), + zero); + + current = current is null + ? keyExpr + : Expression.AndAlso(current, keyExpr); + } + + var greaterThan = forward + ? key.Ascending + : !key.Ascending; + + keyExpr = + greaterThan + ? Expression.GreaterThan( + Expression.Call( + Expression.Property(entity, key.Property), + key.CompareMethod, + cursorExpr[i]), + zero) + : Expression.LessThan( + Expression.Call( + Expression.Property(entity, key.Property), + key.CompareMethod, + cursorExpr[i]), + zero); + + current = current is null + ? keyExpr + : Expression.AndAlso(current, keyExpr); + expression = expression is null + ? current + : Expression.OrElse(expression, current); + handled.Add(key); + } + + return Expression.Lambda>(expression!, entity); + } + + private static Expression CreateParameter(object? value, Type type) + { + var converter = _cachedConverters.GetOrAdd( + type, + t => + { + var method = _createAndConvert.MakeGenericMethod(t); + return v => (Expression)method.Invoke(null, [v,])!; + }); + + return converter(value); + } + + private static Expression CreateAndConvertParameter(object value) + { + Expression> lambda = () => (T)value; + return lambda.Body; + } +} \ No newline at end of file diff --git a/src/HotChocolate/Data/src/EntityFramework.Helpers/Paging/Page.cs b/src/HotChocolate/Data/src/EntityFramework.Helpers/Paging/Page.cs new file mode 100644 index 00000000000..3a48a314f5d --- /dev/null +++ b/src/HotChocolate/Data/src/EntityFramework.Helpers/Paging/Page.cs @@ -0,0 +1,80 @@ +using System.Collections; + +namespace HotChocolate.Data; + +/// +/// Represents a page of a result set. +/// +/// +/// The items of the page. +/// +/// +/// Defines if there is a next page. +/// +/// +/// Defines if there is a previous page. +/// +/// +/// A delegate to create a cursor for an item. +/// +/// +/// The type of the items. +/// +public readonly struct Page( + IReadOnlyList items, + bool hasNextPage, + bool hasPreviousPage, + Func createCursor) + : IEnumerable +{ + /// + /// Gets the items of this page. + /// + public IReadOnlyList Items => items; + + /// + /// Gets the first item of this page. + /// + public T? First => items.Count > 0 ? items[0] : default; + + /// + /// Gets the last item of this page. + /// + public T? Last => items.Count > 0 ? items[^1] : default; + + /// + /// Defines if there is a next page. + /// + public bool HasNextPage => hasNextPage; + + /// + /// Defines if there is a previous page. + /// + public bool HasPreviousPage => hasPreviousPage; + + /// + /// Creates a cursor for an item of this page. + /// + /// + /// The item for which a cursor shall be created. + /// + /// + /// Returns a cursor for the item. + /// + public string CreateCursor(T item) => createCursor(item); + + /// + /// An empty page. + /// + public static Page Empty => new(Array.Empty(), false, false, _ => string.Empty); + + /// + /// Gets the enumerator for the items of this page. + /// + /// + public IEnumerator GetEnumerator() + => items.GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() + => GetEnumerator(); +} \ No newline at end of file diff --git a/src/HotChocolate/Data/src/EntityFramework.Helpers/Paging/PageKey.cs b/src/HotChocolate/Data/src/EntityFramework.Helpers/Paging/PageKey.cs new file mode 100644 index 00000000000..ae47cd4755f --- /dev/null +++ b/src/HotChocolate/Data/src/EntityFramework.Helpers/Paging/PageKey.cs @@ -0,0 +1,15 @@ +namespace HotChocolate.Data; + +/// +/// The paging key can be used when offloading paging logic to a DataLoader. +/// +/// +/// The actual parent key that is used to load the page. +/// +/// +/// The paging arguments that shall be used to load the page. +/// +/// +/// The type of the parent key. +/// +public readonly record struct PageKey(T Key, PagingArguments PagingArgs); \ No newline at end of file diff --git a/src/HotChocolate/Data/src/EntityFramework.Helpers/Paging/PagingArguments.cs b/src/HotChocolate/Data/src/EntityFramework.Helpers/Paging/PagingArguments.cs new file mode 100644 index 00000000000..345597649b6 --- /dev/null +++ b/src/HotChocolate/Data/src/EntityFramework.Helpers/Paging/PagingArguments.cs @@ -0,0 +1,80 @@ +namespace HotChocolate.Data; + +/// +/// The paging arguments are used to specify the paging behavior. +/// +public readonly record struct PagingArguments +{ + /// + /// Initializes a new instance of . + /// + /// + /// The number of entities that shall be taken from the beginning of the list. + /// + /// + /// The cursor after which entities shall be taken. + /// + /// + /// The number of entities that shall be taken from the end of the list. + /// + /// + /// The cursor before which entities shall be taken. + /// + public PagingArguments(int? first = null, + string? after = null, + int? last = null, + string? before = null) + { + First = first; + After = after; + Last = last; + Before = before; + } + + /// + /// The number of entities that shall be taken from the beginning of the list. + /// + public int? First { get; init; } + + /// + /// The cursor after which entities shall be taken. + /// + public string? After { get; init; } + + /// + /// The number of entities that shall be taken from the end of the list. + /// + public int? Last { get; init; } + + /// + /// The cursor before which entities shall be taken. + /// + public string? Before { get; init; } + + /// + /// Deconstructs the paging arguments into its components. + /// + /// + /// The number of entities that shall be taken from the beginning of the list. + /// + /// + /// The cursor after which entities shall be taken. + /// + /// + /// The number of entities that shall be taken from the end of the list. + /// + /// + /// The cursor before which entities shall be taken. + /// + public void Deconstruct( + out int? first, + out string? after, + out int? last, + out string? before) + { + first = First; + after = After; + last = Last; + before = Before; + } +} \ No newline at end of file diff --git a/src/HotChocolate/Data/src/EntityFramework/Extensions/PagingResultExtensions.cs b/src/HotChocolate/Data/src/EntityFramework/Extensions/PagingResultExtensions.cs new file mode 100644 index 00000000000..49503c24c62 --- /dev/null +++ b/src/HotChocolate/Data/src/EntityFramework/Extensions/PagingResultExtensions.cs @@ -0,0 +1,37 @@ +using HotChocolate.Types.Pagination; + +namespace HotChocolate.Data; + +/// +/// Extensions for . +/// +public static class PagingResultExtensions +{ + /// + /// Converts a to a . + /// + /// + /// The page result. + /// + /// + /// The type of the items in the page. + /// + /// + public static async Task> ToConnectionAsync( + this Task> resultPromise) + where T : class + { + var result = await resultPromise; + + return new Connection( + result.Items.Select(t => new Edge(t, result.CreateCursor)).ToArray(), + new ConnectionPageInfo( + result.HasPreviousPage, + result.HasNextPage, + CreateCursor(result.First, result.CreateCursor), + CreateCursor(result.Last, result.CreateCursor))); + } + + private static string? CreateCursor(T? item, Func createCursor) where T : class + => item is null ? null : createCursor(item); +} \ No newline at end of file diff --git a/src/HotChocolate/Data/src/EntityFramework/HotChocolate.Data.EntityFramework.csproj b/src/HotChocolate/Data/src/EntityFramework/HotChocolate.Data.EntityFramework.csproj index 09ba8fa2337..cb438535fec 100644 --- a/src/HotChocolate/Data/src/EntityFramework/HotChocolate.Data.EntityFramework.csproj +++ b/src/HotChocolate/Data/src/EntityFramework/HotChocolate.Data.EntityFramework.csproj @@ -10,6 +10,7 @@ + diff --git a/src/HotChocolate/Data/test/Data.EntityFramework.Tests/BookContext.cs b/src/HotChocolate/Data/test/Data.EntityFramework.Tests/BookContext.cs index 9ee37a70537..06ac8b952b1 100644 --- a/src/HotChocolate/Data/test/Data.EntityFramework.Tests/BookContext.cs +++ b/src/HotChocolate/Data/test/Data.EntityFramework.Tests/BookContext.cs @@ -2,12 +2,8 @@ namespace HotChocolate.Data; -public class BookContext : DbContext +public class BookContext(DbContextOptions options) : DbContext(options) { - public BookContext(DbContextOptions options) : base(options) - { - } - public DbSet Books { get; set; } = default!; public DbSet Authors { get; set; } = default!; @@ -17,10 +13,8 @@ public BookContext(DbContextOptions options) : base(options) public DbSet ZeroAuthors { get; set; } = default!; protected override void OnModelCreating(ModelBuilder modelBuilder) - { - modelBuilder.Entity() + => modelBuilder.Entity() .HasMany(t => t.Books) .WithOne(t => t.Author!) .HasForeignKey(t => t.AuthorId); - } } diff --git a/src/HotChocolate/Data/test/Data.EntityFramework.Tests/DatabaseContext.cs b/src/HotChocolate/Data/test/Data.EntityFramework.Tests/DatabaseContext.cs index d64cafe7e7a..98c91dabcc1 100644 --- a/src/HotChocolate/Data/test/Data.EntityFramework.Tests/DatabaseContext.cs +++ b/src/HotChocolate/Data/test/Data.EntityFramework.Tests/DatabaseContext.cs @@ -2,12 +2,8 @@ namespace HotChocolate.Data; -public class DatabaseContext : DbContext +public class DatabaseContext(DbContextOptions options) : DbContext(options) where T : class { - public DatabaseContext(DbContextOptions options) : base(options) - { - } - public DbSet Data { get; set; } = default!; } diff --git a/src/HotChocolate/Data/test/Data.EntityFramework.Tests/EntityFrameworkExecutableTests.cs b/src/HotChocolate/Data/test/Data.EntityFramework.Tests/EntityFrameworkExecutableTests.cs index a715a54da62..4749cac3bc5 100644 --- a/src/HotChocolate/Data/test/Data.EntityFramework.Tests/EntityFrameworkExecutableTests.cs +++ b/src/HotChocolate/Data/test/Data.EntityFramework.Tests/EntityFrameworkExecutableTests.cs @@ -4,14 +4,10 @@ namespace HotChocolate.Data; -public class EntityFrameworkExecutableTests : IClassFixture +public class EntityFrameworkExecutableTests(AuthorFixture authorFixture) + : IClassFixture { - private readonly BookContext _context; - - public EntityFrameworkExecutableTests(AuthorFixture authorFixture) - { - _context = authorFixture.Context; - } + private readonly BookContext _context = authorFixture.Context; [Fact] public void Extensions_Should_ReturnEntityFrameworkExecutable_When_DBSet() diff --git a/src/HotChocolate/Data/test/Data.EntityFramework.Tests/EntityFrameworkResolverCompilerIntegrationTests.cs b/src/HotChocolate/Data/test/Data.EntityFramework.Tests/EntityFrameworkResolverCompilerIntegrationTests.cs index f8a4d0bda7e..bed733be332 100644 --- a/src/HotChocolate/Data/test/Data.EntityFramework.Tests/EntityFrameworkResolverCompilerIntegrationTests.cs +++ b/src/HotChocolate/Data/test/Data.EntityFramework.Tests/EntityFrameworkResolverCompilerIntegrationTests.cs @@ -1,6 +1,3 @@ -using System.Linq; -using System.Threading; -using System.Threading.Tasks; using CookieCrumble; using HotChocolate.Execution; using Microsoft.EntityFrameworkCore; diff --git a/src/HotChocolate/Data/test/Data.EntityFramework.Tests/HotChocolate.Data.EntityFramework.Tests.csproj b/src/HotChocolate/Data/test/Data.EntityFramework.Tests/HotChocolate.Data.EntityFramework.Tests.csproj index 213a53742bc..ce842ac2086 100644 --- a/src/HotChocolate/Data/test/Data.EntityFramework.Tests/HotChocolate.Data.EntityFramework.Tests.csproj +++ b/src/HotChocolate/Data/test/Data.EntityFramework.Tests/HotChocolate.Data.EntityFramework.Tests.csproj @@ -12,16 +12,23 @@ + + + + + + + diff --git a/src/HotChocolate/Data/test/Data.EntityFramework.Tests/PagingHelperTests.cs b/src/HotChocolate/Data/test/Data.EntityFramework.Tests/PagingHelperTests.cs new file mode 100644 index 00000000000..95890d98089 --- /dev/null +++ b/src/HotChocolate/Data/test/Data.EntityFramework.Tests/PagingHelperTests.cs @@ -0,0 +1,155 @@ +using HotChocolate.Data.TestContext; +using CookieCrumble; +using Microsoft.EntityFrameworkCore; +using Squadron; + +namespace HotChocolate.Data; + +public class PagingHelperTests(PostgreSqlResource resource) : IClassFixture +{ + public PostgreSqlResource Resource { get; } = resource; + + private string CreateConnectionString() + => Resource.GetConnectionString($"db_{Guid.NewGuid():N}"); + + [Fact] + public async Task Fetch_First_2_Items() + { + // Arrange + var connectionString = CreateConnectionString(); + await SeedAsync(connectionString); + + // Act + var arguments = new PagingArguments(2); + await using var context = new CatalogContext(connectionString); + var page = await context.Products.OrderBy(t => t.Name).ThenBy(t => t.Id).ToPageAsync(arguments); + + // Assert + page.MatchMarkdownSnapshot(); + } + + [Fact] + public async Task Fetch_First_2_Items_Second_Page() + { + // Arrange + var connectionString = CreateConnectionString(); + await SeedAsync(connectionString); + + // .. get first page + var arguments = new PagingArguments(2); + await using var context = new CatalogContext(connectionString); + var page = await context.Products.OrderBy(t => t.Name).ThenBy(t => t.Id).ToPageAsync(arguments); + + // Act + arguments = new PagingArguments(2, after: page.CreateCursor(page.Last!)); + page = await context.Products.OrderBy(t => t.Name).ThenBy(t => t.Id).ToPageAsync(arguments); + + // Assert + page.MatchMarkdownSnapshot(); + } + + [Fact] + public async Task Fetch_First_2_Items_Third_Page() + { + // Arrange + var connectionString = CreateConnectionString(); + await SeedAsync(connectionString); + + // .. get first page + var arguments = new PagingArguments(2); + await using var context = new CatalogContext(connectionString); + var page = await context.Products.OrderBy(t => t.Name).ThenBy(t => t.Id).ToPageAsync(arguments); + + arguments = new PagingArguments(2, after: page.CreateCursor(page.Last!)); + page = await context.Products.OrderBy(t => t.Name).ThenBy(t => t.Id).ToPageAsync(arguments); + + // Act + arguments = new PagingArguments(2, after: page.CreateCursor(page.Last!)); + page = await context.Products.OrderBy(t => t.Name).ThenBy(t => t.Id).ToPageAsync(arguments); + + // Assert + page.MatchMarkdownSnapshot(); + } + + [Fact] + public async Task Fetch_Last_2_Items() + { + // Arrange + var connectionString = CreateConnectionString(); + await SeedAsync(connectionString); + + // Act + var arguments = new PagingArguments(last: 2); + await using var context = new CatalogContext(connectionString); + var page = await context.Products.OrderBy(t => t.Name).ThenBy(t => t.Id).ToPageAsync(arguments); + + // Assert + page.MatchMarkdownSnapshot(); + } + + [Fact] + public async Task Fetch_Last_2_Items_Before_Last_Page() + { + // Arrange + var connectionString = CreateConnectionString(); + await SeedAsync(connectionString); + + // .. get last page + var arguments = new PagingArguments(last: 2); + await using var context = new CatalogContext(connectionString); + var page = await context.Products.OrderBy(t => t.Name).ThenBy(t => t.Id).ToPageAsync(arguments); + + // Act + arguments = arguments with { Before = page.CreateCursor(page.First!), }; + page = await context.Products.OrderBy(t => t.Name).ThenBy(t => t.Id).ToPageAsync(arguments); + + // Assert + page.MatchMarkdownSnapshot(); + } + + [Fact] + public async Task Batch_Fetch_First_2_Items() + { + // Arrange + var connectionString = CreateConnectionString(); + await SeedAsync(connectionString); + + // Act + var arguments = new PagingArguments(2); + await using var context = new CatalogContext(connectionString); + var page = await context.Brands + .Include(t => t.Products.OrderBy(p => p.Name).ThenBy(p => p.Id)) + .ToBatchPageAsync(t => t.Id, arguments); + + // Assert + page.MatchMarkdownSnapshot(); + } + + private static async Task SeedAsync(string connectionString) + { + await using var context = new CatalogContext(connectionString); + await context.Database.EnsureCreatedAsync(); + + var type = new ProductType { Name = "T-Shirt", }; + context.ProductTypes.Add(type); + + for (var i = 0; i < 100; i++) + { + var brand = new Brand { Name = "Brand" + i, }; + context.Brands.Add(brand); + + for (var j = 0; j < 100; j++) + { + var product = new Product + { + Name = $"Product {i}-{j}", + Type = type, + Brand = brand, + }; + context.Products.Add(product); + } + } + + await context.SaveChangesAsync(); + } +} \ No newline at end of file diff --git a/src/HotChocolate/Data/test/Data.EntityFramework.Tests/TestContext/Brand.cs b/src/HotChocolate/Data/test/Data.EntityFramework.Tests/TestContext/Brand.cs new file mode 100644 index 00000000000..2de8dbf91a8 --- /dev/null +++ b/src/HotChocolate/Data/test/Data.EntityFramework.Tests/TestContext/Brand.cs @@ -0,0 +1,15 @@ +// ReSharper disable CollectionNeverUpdated.Global + +using System.ComponentModel.DataAnnotations; + +namespace HotChocolate.Data.TestContext; + +public class Brand +{ + public int Id { get; set; } + + [Required] + public string Name { get; set; } = default!; + + public ICollection Products { get; } = new List(); +} diff --git a/src/HotChocolate/Data/test/Data.EntityFramework.Tests/TestContext/CatalogContext.cs b/src/HotChocolate/Data/test/Data.EntityFramework.Tests/TestContext/CatalogContext.cs new file mode 100644 index 00000000000..88b50afd34b --- /dev/null +++ b/src/HotChocolate/Data/test/Data.EntityFramework.Tests/TestContext/CatalogContext.cs @@ -0,0 +1,33 @@ +using HotChocolate.Data.TestContext.EntityConfigurations; +using Microsoft.EntityFrameworkCore; + +namespace HotChocolate.Data.TestContext; + +/// +/// Add migrations using the following command inside the 'Catalog.API' project directory: +/// +/// dotnet ef migrations add --context CatalogContext [migration-name] +/// +public class CatalogContext(string connectionString) : DbContext +{ + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + optionsBuilder.UseNpgsql(connectionString); + } + + public DbSet Products { get; set; } = default!; + + public DbSet ProductTypes { get; set; } = default!; + + public DbSet Brands { get; set; } = default!; + + protected override void OnModelCreating(ModelBuilder builder) + { + builder.ApplyConfiguration(new BrandEntityTypeConfiguration()); + builder.ApplyConfiguration(new ProductTypeEntityTypeConfiguration()); + builder.ApplyConfiguration(new ProductEntityTypeConfiguration()); + + // Add the outbox table to this context + // builder.UseIntegrationEventLogs(); + } +} \ No newline at end of file diff --git a/src/HotChocolate/Data/test/Data.EntityFramework.Tests/TestContext/EntityConfigurations/BrandEntityTypeConfiguration.cs b/src/HotChocolate/Data/test/Data.EntityFramework.Tests/TestContext/EntityConfigurations/BrandEntityTypeConfiguration.cs new file mode 100644 index 00000000000..88a38bd0f44 --- /dev/null +++ b/src/HotChocolate/Data/test/Data.EntityFramework.Tests/TestContext/EntityConfigurations/BrandEntityTypeConfiguration.cs @@ -0,0 +1,17 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace HotChocolate.Data.TestContext.EntityConfigurations; + +internal sealed class BrandEntityTypeConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder + .ToTable("Brands"); + + builder + .Property(cb => cb.Name) + .HasMaxLength(100); + } +} diff --git a/src/HotChocolate/Data/test/Data.EntityFramework.Tests/TestContext/EntityConfigurations/ProductEntityTypeConfiguration.cs b/src/HotChocolate/Data/test/Data.EntityFramework.Tests/TestContext/EntityConfigurations/ProductEntityTypeConfiguration.cs new file mode 100644 index 00000000000..d22ea0fddbb --- /dev/null +++ b/src/HotChocolate/Data/test/Data.EntityFramework.Tests/TestContext/EntityConfigurations/ProductEntityTypeConfiguration.cs @@ -0,0 +1,42 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace HotChocolate.Data.TestContext.EntityConfigurations; + +internal sealed class ProductEntityTypeConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder + .ToTable("Products"); + + builder + .Property(ci => ci.Name) + .HasMaxLength(50); + + builder + .Property(ci => ci.Description) + .HasMaxLength(2048); + + builder + .Property(ci => ci.ImageFileName) + .HasMaxLength(256); + + /* + builder + .Property(ci => ci.Embedding) + .HasColumnType("vector(1536)"); + */ + + builder + .HasOne(ci => ci.Brand) + .WithMany(ci => ci.Products); + + builder + .HasOne(ci => ci.Type) + .WithMany(ci => ci.Products); + + builder + .HasIndex(ci => ci.Name); + } +} diff --git a/src/HotChocolate/Data/test/Data.EntityFramework.Tests/TestContext/EntityConfigurations/ProductTypeEntityTypeConfiguration.cs b/src/HotChocolate/Data/test/Data.EntityFramework.Tests/TestContext/EntityConfigurations/ProductTypeEntityTypeConfiguration.cs new file mode 100644 index 00000000000..c8faf3df271 --- /dev/null +++ b/src/HotChocolate/Data/test/Data.EntityFramework.Tests/TestContext/EntityConfigurations/ProductTypeEntityTypeConfiguration.cs @@ -0,0 +1,17 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace HotChocolate.Data.TestContext.EntityConfigurations; + +internal sealed class ProductTypeEntityTypeConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder + .ToTable("ProductTypes"); + + builder + .Property(cb => cb.Name) + .HasMaxLength(100); + } +} diff --git a/src/HotChocolate/Data/test/Data.EntityFramework.Tests/TestContext/Product.cs b/src/HotChocolate/Data/test/Data.EntityFramework.Tests/TestContext/Product.cs new file mode 100644 index 00000000000..1dedbd0edcf --- /dev/null +++ b/src/HotChocolate/Data/test/Data.EntityFramework.Tests/TestContext/Product.cs @@ -0,0 +1,104 @@ +// ReSharper disable CollectionNeverUpdated.Global + +using System.ComponentModel.DataAnnotations; + +namespace HotChocolate.Data.TestContext; + +public class Product +{ + public int Id { get; set; } + + [Required] + public string Name { get; set; } = default!; + + public string? Description { get; set; } + + public decimal Price { get; set; } + + public string? ImageFileName { get; set; } + + public int TypeId { get; set; } + + public ProductType? Type { get; set; } + + public int BrandId { get; set; } + + public Brand? Brand { get; set; } + + // Quantity in stock + public int AvailableStock { get; set; } + + // Available stock at which we should reorder + public int RestockThreshold { get; set; } + + + // Maximum number of units that can be in-stock at any time (due to physicial/logistical constraints in warehouses) + public int MaxStockThreshold { get; set; } + + /// Optional embedding for the catalog item's description. + // [JsonIgnore] + // public Vector Embedding { get; set; } + + /// + /// True if item is on reorder + /// + public bool OnReorder { get; set; } + + + /// + /// Decrements the quantity of a particular item in inventory and ensures the restockThreshold hasn't + /// been breached. If so, a RestockRequest is generated in CheckThreshold. + /// + /// If there is sufficient stock of an item, then the integer returned at the end of this call should be the same as quantityDesired. + /// In the event that there is not sufficient stock available, the method will remove whatever stock is available and return that quantity to the client. + /// In this case, it is the responsibility of the client to determine if the amount that is returned is the same as quantityDesired. + /// It is invalid to pass in a negative number. + /// + /// + /// int: Returns the number actually removed from stock. + /// + public int RemoveStock(int quantityDesired) + { + if (AvailableStock == 0) + { + // throw new CatalogDomainException($"Empty stock, product item {Name} is sold out"); + } + + if (quantityDesired <= 0) + { + // throw new CatalogDomainException($"Item units desired should be greater than zero"); + } + + var removed = Math.Min(quantityDesired, AvailableStock); + + AvailableStock -= removed; + + return removed; + } + + /// + /// Increments the quantity of a particular item in inventory. + /// + /// int: Returns the quantity that has been added to stock + /// + public int AddStock(int quantity) + { + int original = AvailableStock; + + // The quantity that the client is trying to add to stock is greater than what can be physically accommodated in the Warehouse + if ((AvailableStock + quantity) > MaxStockThreshold) + { + // For now, this method only adds new units up maximum stock threshold. In an expanded version of this application, we + //could include tracking for the remaining units and store information about overstock elsewhere. + AvailableStock += (MaxStockThreshold - AvailableStock); + } + else + { + AvailableStock += quantity; + } + + OnReorder = false; + + return AvailableStock - original; + } +} diff --git a/src/HotChocolate/Data/test/Data.EntityFramework.Tests/TestContext/ProductImage.cs b/src/HotChocolate/Data/test/Data.EntityFramework.Tests/TestContext/ProductImage.cs new file mode 100644 index 00000000000..4e6356a926e --- /dev/null +++ b/src/HotChocolate/Data/test/Data.EntityFramework.Tests/TestContext/ProductImage.cs @@ -0,0 +1,3 @@ +namespace HotChocolate.Data.TestContext; + +public sealed record ProductImage(string Name, Func OpenStream); \ No newline at end of file diff --git a/src/HotChocolate/Data/test/Data.EntityFramework.Tests/TestContext/ProductType.cs b/src/HotChocolate/Data/test/Data.EntityFramework.Tests/TestContext/ProductType.cs new file mode 100644 index 00000000000..9100901bba8 --- /dev/null +++ b/src/HotChocolate/Data/test/Data.EntityFramework.Tests/TestContext/ProductType.cs @@ -0,0 +1,14 @@ +// ReSharper disable CollectionNeverUpdated.Global + +using System.ComponentModel.DataAnnotations; + +namespace HotChocolate.Data.TestContext; + +public class ProductType +{ + public int Id { get; set; } + + [Required] public string Name { get; set; } = default!; + + public ICollection Products { get; } = new List(); +} diff --git a/src/HotChocolate/Data/test/Data.EntityFramework.Tests/__snapshots__/PagingHelperTests.Batch_Fetch_First_2_Items.md b/src/HotChocolate/Data/test/Data.EntityFramework.Tests/__snapshots__/PagingHelperTests.Batch_Fetch_First_2_Items.md new file mode 100644 index 00000000000..58e2488f5bf --- /dev/null +++ b/src/HotChocolate/Data/test/Data.EntityFramework.Tests/__snapshots__/PagingHelperTests.Batch_Fetch_First_2_Items.md @@ -0,0 +1,7006 @@ +# Batch_Fetch_First_2_Items + +```json +{ + "PageKey { Key = 1, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 1, + "Name": "Product 0-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 1, + "Brand": { + "Id": 1, + "Name": "Brand0", + "Products": [ + { + "Id": 2, + "Name": "Product 0-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 1, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 2, + "Name": "Product 0-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 1, + "Brand": { + "Id": 1, + "Name": "Brand0", + "Products": [ + { + "Id": 1, + "Name": "Product 0-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 1, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 2, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 101, + "Name": "Product 1-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 2, + "Brand": { + "Id": 2, + "Name": "Brand1", + "Products": [ + { + "Id": 102, + "Name": "Product 1-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 2, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 102, + "Name": "Product 1-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 2, + "Brand": { + "Id": 2, + "Name": "Brand1", + "Products": [ + { + "Id": 101, + "Name": "Product 1-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 2, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 3, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 201, + "Name": "Product 2-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 3, + "Brand": { + "Id": 3, + "Name": "Brand2", + "Products": [ + { + "Id": 202, + "Name": "Product 2-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 3, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 202, + "Name": "Product 2-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 3, + "Brand": { + "Id": 3, + "Name": "Brand2", + "Products": [ + { + "Id": 201, + "Name": "Product 2-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 3, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 4, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 301, + "Name": "Product 3-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 4, + "Brand": { + "Id": 4, + "Name": "Brand3", + "Products": [ + { + "Id": 302, + "Name": "Product 3-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 4, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 302, + "Name": "Product 3-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 4, + "Brand": { + "Id": 4, + "Name": "Brand3", + "Products": [ + { + "Id": 301, + "Name": "Product 3-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 4, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 5, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 401, + "Name": "Product 4-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 5, + "Brand": { + "Id": 5, + "Name": "Brand4", + "Products": [ + { + "Id": 402, + "Name": "Product 4-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 5, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 402, + "Name": "Product 4-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 5, + "Brand": { + "Id": 5, + "Name": "Brand4", + "Products": [ + { + "Id": 401, + "Name": "Product 4-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 5, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 6, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 501, + "Name": "Product 5-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 6, + "Brand": { + "Id": 6, + "Name": "Brand5", + "Products": [ + { + "Id": 502, + "Name": "Product 5-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 6, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 502, + "Name": "Product 5-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 6, + "Brand": { + "Id": 6, + "Name": "Brand5", + "Products": [ + { + "Id": 501, + "Name": "Product 5-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 6, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 7, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 601, + "Name": "Product 6-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 7, + "Brand": { + "Id": 7, + "Name": "Brand6", + "Products": [ + { + "Id": 602, + "Name": "Product 6-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 7, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 602, + "Name": "Product 6-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 7, + "Brand": { + "Id": 7, + "Name": "Brand6", + "Products": [ + { + "Id": 601, + "Name": "Product 6-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 7, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 8, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 701, + "Name": "Product 7-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 8, + "Brand": { + "Id": 8, + "Name": "Brand7", + "Products": [ + { + "Id": 702, + "Name": "Product 7-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 8, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 702, + "Name": "Product 7-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 8, + "Brand": { + "Id": 8, + "Name": "Brand7", + "Products": [ + { + "Id": 701, + "Name": "Product 7-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 8, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 9, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 801, + "Name": "Product 8-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 9, + "Brand": { + "Id": 9, + "Name": "Brand8", + "Products": [ + { + "Id": 802, + "Name": "Product 8-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 9, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 802, + "Name": "Product 8-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 9, + "Brand": { + "Id": 9, + "Name": "Brand8", + "Products": [ + { + "Id": 801, + "Name": "Product 8-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 9, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 10, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 901, + "Name": "Product 9-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 10, + "Brand": { + "Id": 10, + "Name": "Brand9", + "Products": [ + { + "Id": 902, + "Name": "Product 9-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 10, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 902, + "Name": "Product 9-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 10, + "Brand": { + "Id": 10, + "Name": "Brand9", + "Products": [ + { + "Id": 901, + "Name": "Product 9-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 10, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 11, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 1001, + "Name": "Product 10-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 11, + "Brand": { + "Id": 11, + "Name": "Brand10", + "Products": [ + { + "Id": 1002, + "Name": "Product 10-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 11, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 1002, + "Name": "Product 10-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 11, + "Brand": { + "Id": 11, + "Name": "Brand10", + "Products": [ + { + "Id": 1001, + "Name": "Product 10-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 11, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 12, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 1101, + "Name": "Product 11-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 12, + "Brand": { + "Id": 12, + "Name": "Brand11", + "Products": [ + { + "Id": 1102, + "Name": "Product 11-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 12, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 1102, + "Name": "Product 11-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 12, + "Brand": { + "Id": 12, + "Name": "Brand11", + "Products": [ + { + "Id": 1101, + "Name": "Product 11-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 12, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 13, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 1201, + "Name": "Product 12-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 13, + "Brand": { + "Id": 13, + "Name": "Brand12", + "Products": [ + { + "Id": 1202, + "Name": "Product 12-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 13, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 1202, + "Name": "Product 12-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 13, + "Brand": { + "Id": 13, + "Name": "Brand12", + "Products": [ + { + "Id": 1201, + "Name": "Product 12-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 13, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 14, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 1301, + "Name": "Product 13-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 14, + "Brand": { + "Id": 14, + "Name": "Brand13", + "Products": [ + { + "Id": 1302, + "Name": "Product 13-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 14, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 1302, + "Name": "Product 13-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 14, + "Brand": { + "Id": 14, + "Name": "Brand13", + "Products": [ + { + "Id": 1301, + "Name": "Product 13-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 14, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 15, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 1401, + "Name": "Product 14-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 15, + "Brand": { + "Id": 15, + "Name": "Brand14", + "Products": [ + { + "Id": 1402, + "Name": "Product 14-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 15, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 1402, + "Name": "Product 14-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 15, + "Brand": { + "Id": 15, + "Name": "Brand14", + "Products": [ + { + "Id": 1401, + "Name": "Product 14-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 15, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 16, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 1501, + "Name": "Product 15-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 16, + "Brand": { + "Id": 16, + "Name": "Brand15", + "Products": [ + { + "Id": 1502, + "Name": "Product 15-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 16, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 1502, + "Name": "Product 15-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 16, + "Brand": { + "Id": 16, + "Name": "Brand15", + "Products": [ + { + "Id": 1501, + "Name": "Product 15-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 16, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 17, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 1601, + "Name": "Product 16-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 17, + "Brand": { + "Id": 17, + "Name": "Brand16", + "Products": [ + { + "Id": 1602, + "Name": "Product 16-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 17, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 1602, + "Name": "Product 16-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 17, + "Brand": { + "Id": 17, + "Name": "Brand16", + "Products": [ + { + "Id": 1601, + "Name": "Product 16-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 17, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 18, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 1701, + "Name": "Product 17-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 18, + "Brand": { + "Id": 18, + "Name": "Brand17", + "Products": [ + { + "Id": 1702, + "Name": "Product 17-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 18, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 1702, + "Name": "Product 17-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 18, + "Brand": { + "Id": 18, + "Name": "Brand17", + "Products": [ + { + "Id": 1701, + "Name": "Product 17-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 18, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 19, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 1801, + "Name": "Product 18-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 19, + "Brand": { + "Id": 19, + "Name": "Brand18", + "Products": [ + { + "Id": 1802, + "Name": "Product 18-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 19, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 1802, + "Name": "Product 18-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 19, + "Brand": { + "Id": 19, + "Name": "Brand18", + "Products": [ + { + "Id": 1801, + "Name": "Product 18-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 19, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 20, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 1901, + "Name": "Product 19-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 20, + "Brand": { + "Id": 20, + "Name": "Brand19", + "Products": [ + { + "Id": 1902, + "Name": "Product 19-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 20, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 1902, + "Name": "Product 19-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 20, + "Brand": { + "Id": 20, + "Name": "Brand19", + "Products": [ + { + "Id": 1901, + "Name": "Product 19-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 20, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 21, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 2001, + "Name": "Product 20-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 21, + "Brand": { + "Id": 21, + "Name": "Brand20", + "Products": [ + { + "Id": 2002, + "Name": "Product 20-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 21, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 2002, + "Name": "Product 20-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 21, + "Brand": { + "Id": 21, + "Name": "Brand20", + "Products": [ + { + "Id": 2001, + "Name": "Product 20-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 21, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 22, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 2101, + "Name": "Product 21-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 22, + "Brand": { + "Id": 22, + "Name": "Brand21", + "Products": [ + { + "Id": 2102, + "Name": "Product 21-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 22, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 2102, + "Name": "Product 21-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 22, + "Brand": { + "Id": 22, + "Name": "Brand21", + "Products": [ + { + "Id": 2101, + "Name": "Product 21-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 22, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 23, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 2201, + "Name": "Product 22-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 23, + "Brand": { + "Id": 23, + "Name": "Brand22", + "Products": [ + { + "Id": 2202, + "Name": "Product 22-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 23, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 2202, + "Name": "Product 22-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 23, + "Brand": { + "Id": 23, + "Name": "Brand22", + "Products": [ + { + "Id": 2201, + "Name": "Product 22-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 23, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 24, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 2301, + "Name": "Product 23-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 24, + "Brand": { + "Id": 24, + "Name": "Brand23", + "Products": [ + { + "Id": 2302, + "Name": "Product 23-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 24, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 2302, + "Name": "Product 23-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 24, + "Brand": { + "Id": 24, + "Name": "Brand23", + "Products": [ + { + "Id": 2301, + "Name": "Product 23-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 24, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 25, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 2401, + "Name": "Product 24-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 25, + "Brand": { + "Id": 25, + "Name": "Brand24", + "Products": [ + { + "Id": 2402, + "Name": "Product 24-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 25, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 2402, + "Name": "Product 24-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 25, + "Brand": { + "Id": 25, + "Name": "Brand24", + "Products": [ + { + "Id": 2401, + "Name": "Product 24-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 25, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 26, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 2501, + "Name": "Product 25-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 26, + "Brand": { + "Id": 26, + "Name": "Brand25", + "Products": [ + { + "Id": 2502, + "Name": "Product 25-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 26, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 2502, + "Name": "Product 25-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 26, + "Brand": { + "Id": 26, + "Name": "Brand25", + "Products": [ + { + "Id": 2501, + "Name": "Product 25-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 26, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 27, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 2601, + "Name": "Product 26-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 27, + "Brand": { + "Id": 27, + "Name": "Brand26", + "Products": [ + { + "Id": 2602, + "Name": "Product 26-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 27, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 2602, + "Name": "Product 26-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 27, + "Brand": { + "Id": 27, + "Name": "Brand26", + "Products": [ + { + "Id": 2601, + "Name": "Product 26-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 27, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 28, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 2701, + "Name": "Product 27-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 28, + "Brand": { + "Id": 28, + "Name": "Brand27", + "Products": [ + { + "Id": 2702, + "Name": "Product 27-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 28, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 2702, + "Name": "Product 27-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 28, + "Brand": { + "Id": 28, + "Name": "Brand27", + "Products": [ + { + "Id": 2701, + "Name": "Product 27-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 28, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 29, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 2801, + "Name": "Product 28-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 29, + "Brand": { + "Id": 29, + "Name": "Brand28", + "Products": [ + { + "Id": 2802, + "Name": "Product 28-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 29, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 2802, + "Name": "Product 28-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 29, + "Brand": { + "Id": 29, + "Name": "Brand28", + "Products": [ + { + "Id": 2801, + "Name": "Product 28-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 29, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 30, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 2901, + "Name": "Product 29-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 30, + "Brand": { + "Id": 30, + "Name": "Brand29", + "Products": [ + { + "Id": 2902, + "Name": "Product 29-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 30, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 2902, + "Name": "Product 29-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 30, + "Brand": { + "Id": 30, + "Name": "Brand29", + "Products": [ + { + "Id": 2901, + "Name": "Product 29-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 30, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 31, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 3001, + "Name": "Product 30-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 31, + "Brand": { + "Id": 31, + "Name": "Brand30", + "Products": [ + { + "Id": 3002, + "Name": "Product 30-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 31, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 3002, + "Name": "Product 30-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 31, + "Brand": { + "Id": 31, + "Name": "Brand30", + "Products": [ + { + "Id": 3001, + "Name": "Product 30-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 31, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 32, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 3101, + "Name": "Product 31-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 32, + "Brand": { + "Id": 32, + "Name": "Brand31", + "Products": [ + { + "Id": 3102, + "Name": "Product 31-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 32, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 3102, + "Name": "Product 31-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 32, + "Brand": { + "Id": 32, + "Name": "Brand31", + "Products": [ + { + "Id": 3101, + "Name": "Product 31-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 32, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 33, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 3201, + "Name": "Product 32-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 33, + "Brand": { + "Id": 33, + "Name": "Brand32", + "Products": [ + { + "Id": 3202, + "Name": "Product 32-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 33, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 3202, + "Name": "Product 32-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 33, + "Brand": { + "Id": 33, + "Name": "Brand32", + "Products": [ + { + "Id": 3201, + "Name": "Product 32-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 33, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 34, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 3301, + "Name": "Product 33-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 34, + "Brand": { + "Id": 34, + "Name": "Brand33", + "Products": [ + { + "Id": 3302, + "Name": "Product 33-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 34, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 3302, + "Name": "Product 33-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 34, + "Brand": { + "Id": 34, + "Name": "Brand33", + "Products": [ + { + "Id": 3301, + "Name": "Product 33-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 34, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 35, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 3401, + "Name": "Product 34-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 35, + "Brand": { + "Id": 35, + "Name": "Brand34", + "Products": [ + { + "Id": 3402, + "Name": "Product 34-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 35, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 3402, + "Name": "Product 34-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 35, + "Brand": { + "Id": 35, + "Name": "Brand34", + "Products": [ + { + "Id": 3401, + "Name": "Product 34-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 35, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 36, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 3501, + "Name": "Product 35-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 36, + "Brand": { + "Id": 36, + "Name": "Brand35", + "Products": [ + { + "Id": 3502, + "Name": "Product 35-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 36, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 3502, + "Name": "Product 35-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 36, + "Brand": { + "Id": 36, + "Name": "Brand35", + "Products": [ + { + "Id": 3501, + "Name": "Product 35-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 36, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 37, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 3601, + "Name": "Product 36-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 37, + "Brand": { + "Id": 37, + "Name": "Brand36", + "Products": [ + { + "Id": 3602, + "Name": "Product 36-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 37, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 3602, + "Name": "Product 36-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 37, + "Brand": { + "Id": 37, + "Name": "Brand36", + "Products": [ + { + "Id": 3601, + "Name": "Product 36-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 37, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 38, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 3701, + "Name": "Product 37-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 38, + "Brand": { + "Id": 38, + "Name": "Brand37", + "Products": [ + { + "Id": 3702, + "Name": "Product 37-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 38, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 3702, + "Name": "Product 37-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 38, + "Brand": { + "Id": 38, + "Name": "Brand37", + "Products": [ + { + "Id": 3701, + "Name": "Product 37-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 38, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 39, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 3801, + "Name": "Product 38-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 39, + "Brand": { + "Id": 39, + "Name": "Brand38", + "Products": [ + { + "Id": 3802, + "Name": "Product 38-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 39, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 3802, + "Name": "Product 38-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 39, + "Brand": { + "Id": 39, + "Name": "Brand38", + "Products": [ + { + "Id": 3801, + "Name": "Product 38-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 39, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 40, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 3901, + "Name": "Product 39-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 40, + "Brand": { + "Id": 40, + "Name": "Brand39", + "Products": [ + { + "Id": 3902, + "Name": "Product 39-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 40, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 3902, + "Name": "Product 39-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 40, + "Brand": { + "Id": 40, + "Name": "Brand39", + "Products": [ + { + "Id": 3901, + "Name": "Product 39-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 40, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 41, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 4001, + "Name": "Product 40-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 41, + "Brand": { + "Id": 41, + "Name": "Brand40", + "Products": [ + { + "Id": 4002, + "Name": "Product 40-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 41, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 4002, + "Name": "Product 40-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 41, + "Brand": { + "Id": 41, + "Name": "Brand40", + "Products": [ + { + "Id": 4001, + "Name": "Product 40-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 41, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 42, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 4101, + "Name": "Product 41-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 42, + "Brand": { + "Id": 42, + "Name": "Brand41", + "Products": [ + { + "Id": 4102, + "Name": "Product 41-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 42, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 4102, + "Name": "Product 41-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 42, + "Brand": { + "Id": 42, + "Name": "Brand41", + "Products": [ + { + "Id": 4101, + "Name": "Product 41-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 42, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 43, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 4201, + "Name": "Product 42-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 43, + "Brand": { + "Id": 43, + "Name": "Brand42", + "Products": [ + { + "Id": 4202, + "Name": "Product 42-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 43, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 4202, + "Name": "Product 42-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 43, + "Brand": { + "Id": 43, + "Name": "Brand42", + "Products": [ + { + "Id": 4201, + "Name": "Product 42-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 43, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 44, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 4301, + "Name": "Product 43-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 44, + "Brand": { + "Id": 44, + "Name": "Brand43", + "Products": [ + { + "Id": 4302, + "Name": "Product 43-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 44, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 4302, + "Name": "Product 43-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 44, + "Brand": { + "Id": 44, + "Name": "Brand43", + "Products": [ + { + "Id": 4301, + "Name": "Product 43-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 44, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 45, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 4401, + "Name": "Product 44-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 45, + "Brand": { + "Id": 45, + "Name": "Brand44", + "Products": [ + { + "Id": 4402, + "Name": "Product 44-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 45, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 4402, + "Name": "Product 44-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 45, + "Brand": { + "Id": 45, + "Name": "Brand44", + "Products": [ + { + "Id": 4401, + "Name": "Product 44-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 45, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 46, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 4501, + "Name": "Product 45-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 46, + "Brand": { + "Id": 46, + "Name": "Brand45", + "Products": [ + { + "Id": 4502, + "Name": "Product 45-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 46, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 4502, + "Name": "Product 45-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 46, + "Brand": { + "Id": 46, + "Name": "Brand45", + "Products": [ + { + "Id": 4501, + "Name": "Product 45-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 46, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 47, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 4601, + "Name": "Product 46-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 47, + "Brand": { + "Id": 47, + "Name": "Brand46", + "Products": [ + { + "Id": 4602, + "Name": "Product 46-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 47, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 4602, + "Name": "Product 46-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 47, + "Brand": { + "Id": 47, + "Name": "Brand46", + "Products": [ + { + "Id": 4601, + "Name": "Product 46-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 47, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 48, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 4701, + "Name": "Product 47-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 48, + "Brand": { + "Id": 48, + "Name": "Brand47", + "Products": [ + { + "Id": 4702, + "Name": "Product 47-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 48, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 4702, + "Name": "Product 47-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 48, + "Brand": { + "Id": 48, + "Name": "Brand47", + "Products": [ + { + "Id": 4701, + "Name": "Product 47-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 48, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 49, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 4801, + "Name": "Product 48-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 49, + "Brand": { + "Id": 49, + "Name": "Brand48", + "Products": [ + { + "Id": 4802, + "Name": "Product 48-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 49, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 4802, + "Name": "Product 48-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 49, + "Brand": { + "Id": 49, + "Name": "Brand48", + "Products": [ + { + "Id": 4801, + "Name": "Product 48-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 49, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 50, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 4901, + "Name": "Product 49-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 50, + "Brand": { + "Id": 50, + "Name": "Brand49", + "Products": [ + { + "Id": 4902, + "Name": "Product 49-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 50, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 4902, + "Name": "Product 49-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 50, + "Brand": { + "Id": 50, + "Name": "Brand49", + "Products": [ + { + "Id": 4901, + "Name": "Product 49-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 50, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 51, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 5001, + "Name": "Product 50-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 51, + "Brand": { + "Id": 51, + "Name": "Brand50", + "Products": [ + { + "Id": 5002, + "Name": "Product 50-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 51, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 5002, + "Name": "Product 50-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 51, + "Brand": { + "Id": 51, + "Name": "Brand50", + "Products": [ + { + "Id": 5001, + "Name": "Product 50-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 51, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 52, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 5101, + "Name": "Product 51-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 52, + "Brand": { + "Id": 52, + "Name": "Brand51", + "Products": [ + { + "Id": 5102, + "Name": "Product 51-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 52, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 5102, + "Name": "Product 51-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 52, + "Brand": { + "Id": 52, + "Name": "Brand51", + "Products": [ + { + "Id": 5101, + "Name": "Product 51-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 52, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 53, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 5201, + "Name": "Product 52-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 53, + "Brand": { + "Id": 53, + "Name": "Brand52", + "Products": [ + { + "Id": 5202, + "Name": "Product 52-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 53, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 5202, + "Name": "Product 52-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 53, + "Brand": { + "Id": 53, + "Name": "Brand52", + "Products": [ + { + "Id": 5201, + "Name": "Product 52-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 53, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 54, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 5301, + "Name": "Product 53-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 54, + "Brand": { + "Id": 54, + "Name": "Brand53", + "Products": [ + { + "Id": 5302, + "Name": "Product 53-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 54, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 5302, + "Name": "Product 53-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 54, + "Brand": { + "Id": 54, + "Name": "Brand53", + "Products": [ + { + "Id": 5301, + "Name": "Product 53-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 54, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 55, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 5401, + "Name": "Product 54-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 55, + "Brand": { + "Id": 55, + "Name": "Brand54", + "Products": [ + { + "Id": 5402, + "Name": "Product 54-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 55, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 5402, + "Name": "Product 54-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 55, + "Brand": { + "Id": 55, + "Name": "Brand54", + "Products": [ + { + "Id": 5401, + "Name": "Product 54-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 55, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 56, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 5501, + "Name": "Product 55-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 56, + "Brand": { + "Id": 56, + "Name": "Brand55", + "Products": [ + { + "Id": 5502, + "Name": "Product 55-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 56, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 5502, + "Name": "Product 55-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 56, + "Brand": { + "Id": 56, + "Name": "Brand55", + "Products": [ + { + "Id": 5501, + "Name": "Product 55-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 56, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 57, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 5601, + "Name": "Product 56-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 57, + "Brand": { + "Id": 57, + "Name": "Brand56", + "Products": [ + { + "Id": 5602, + "Name": "Product 56-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 57, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 5602, + "Name": "Product 56-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 57, + "Brand": { + "Id": 57, + "Name": "Brand56", + "Products": [ + { + "Id": 5601, + "Name": "Product 56-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 57, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 58, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 5701, + "Name": "Product 57-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 58, + "Brand": { + "Id": 58, + "Name": "Brand57", + "Products": [ + { + "Id": 5702, + "Name": "Product 57-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 58, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 5702, + "Name": "Product 57-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 58, + "Brand": { + "Id": 58, + "Name": "Brand57", + "Products": [ + { + "Id": 5701, + "Name": "Product 57-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 58, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 59, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 5801, + "Name": "Product 58-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 59, + "Brand": { + "Id": 59, + "Name": "Brand58", + "Products": [ + { + "Id": 5802, + "Name": "Product 58-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 59, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 5802, + "Name": "Product 58-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 59, + "Brand": { + "Id": 59, + "Name": "Brand58", + "Products": [ + { + "Id": 5801, + "Name": "Product 58-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 59, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 60, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 5901, + "Name": "Product 59-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 60, + "Brand": { + "Id": 60, + "Name": "Brand59", + "Products": [ + { + "Id": 5902, + "Name": "Product 59-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 60, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 5902, + "Name": "Product 59-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 60, + "Brand": { + "Id": 60, + "Name": "Brand59", + "Products": [ + { + "Id": 5901, + "Name": "Product 59-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 60, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 61, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 6001, + "Name": "Product 60-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 61, + "Brand": { + "Id": 61, + "Name": "Brand60", + "Products": [ + { + "Id": 6002, + "Name": "Product 60-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 61, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 6002, + "Name": "Product 60-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 61, + "Brand": { + "Id": 61, + "Name": "Brand60", + "Products": [ + { + "Id": 6001, + "Name": "Product 60-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 61, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 62, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 6101, + "Name": "Product 61-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 62, + "Brand": { + "Id": 62, + "Name": "Brand61", + "Products": [ + { + "Id": 6102, + "Name": "Product 61-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 62, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 6102, + "Name": "Product 61-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 62, + "Brand": { + "Id": 62, + "Name": "Brand61", + "Products": [ + { + "Id": 6101, + "Name": "Product 61-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 62, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 63, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 6201, + "Name": "Product 62-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 63, + "Brand": { + "Id": 63, + "Name": "Brand62", + "Products": [ + { + "Id": 6202, + "Name": "Product 62-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 63, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 6202, + "Name": "Product 62-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 63, + "Brand": { + "Id": 63, + "Name": "Brand62", + "Products": [ + { + "Id": 6201, + "Name": "Product 62-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 63, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 64, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 6301, + "Name": "Product 63-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 64, + "Brand": { + "Id": 64, + "Name": "Brand63", + "Products": [ + { + "Id": 6302, + "Name": "Product 63-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 64, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 6302, + "Name": "Product 63-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 64, + "Brand": { + "Id": 64, + "Name": "Brand63", + "Products": [ + { + "Id": 6301, + "Name": "Product 63-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 64, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 65, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 6401, + "Name": "Product 64-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 65, + "Brand": { + "Id": 65, + "Name": "Brand64", + "Products": [ + { + "Id": 6402, + "Name": "Product 64-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 65, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 6402, + "Name": "Product 64-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 65, + "Brand": { + "Id": 65, + "Name": "Brand64", + "Products": [ + { + "Id": 6401, + "Name": "Product 64-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 65, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 66, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 6501, + "Name": "Product 65-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 66, + "Brand": { + "Id": 66, + "Name": "Brand65", + "Products": [ + { + "Id": 6502, + "Name": "Product 65-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 66, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 6502, + "Name": "Product 65-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 66, + "Brand": { + "Id": 66, + "Name": "Brand65", + "Products": [ + { + "Id": 6501, + "Name": "Product 65-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 66, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 67, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 6601, + "Name": "Product 66-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 67, + "Brand": { + "Id": 67, + "Name": "Brand66", + "Products": [ + { + "Id": 6602, + "Name": "Product 66-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 67, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 6602, + "Name": "Product 66-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 67, + "Brand": { + "Id": 67, + "Name": "Brand66", + "Products": [ + { + "Id": 6601, + "Name": "Product 66-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 67, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 68, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 6701, + "Name": "Product 67-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 68, + "Brand": { + "Id": 68, + "Name": "Brand67", + "Products": [ + { + "Id": 6702, + "Name": "Product 67-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 68, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 6702, + "Name": "Product 67-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 68, + "Brand": { + "Id": 68, + "Name": "Brand67", + "Products": [ + { + "Id": 6701, + "Name": "Product 67-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 68, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 69, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 6801, + "Name": "Product 68-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 69, + "Brand": { + "Id": 69, + "Name": "Brand68", + "Products": [ + { + "Id": 6802, + "Name": "Product 68-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 69, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 6802, + "Name": "Product 68-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 69, + "Brand": { + "Id": 69, + "Name": "Brand68", + "Products": [ + { + "Id": 6801, + "Name": "Product 68-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 69, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 70, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 6901, + "Name": "Product 69-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 70, + "Brand": { + "Id": 70, + "Name": "Brand69", + "Products": [ + { + "Id": 6902, + "Name": "Product 69-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 70, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 6902, + "Name": "Product 69-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 70, + "Brand": { + "Id": 70, + "Name": "Brand69", + "Products": [ + { + "Id": 6901, + "Name": "Product 69-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 70, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 71, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 7001, + "Name": "Product 70-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 71, + "Brand": { + "Id": 71, + "Name": "Brand70", + "Products": [ + { + "Id": 7002, + "Name": "Product 70-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 71, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 7002, + "Name": "Product 70-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 71, + "Brand": { + "Id": 71, + "Name": "Brand70", + "Products": [ + { + "Id": 7001, + "Name": "Product 70-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 71, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 72, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 7101, + "Name": "Product 71-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 72, + "Brand": { + "Id": 72, + "Name": "Brand71", + "Products": [ + { + "Id": 7102, + "Name": "Product 71-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 72, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 7102, + "Name": "Product 71-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 72, + "Brand": { + "Id": 72, + "Name": "Brand71", + "Products": [ + { + "Id": 7101, + "Name": "Product 71-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 72, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 73, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 7201, + "Name": "Product 72-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 73, + "Brand": { + "Id": 73, + "Name": "Brand72", + "Products": [ + { + "Id": 7202, + "Name": "Product 72-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 73, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 7202, + "Name": "Product 72-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 73, + "Brand": { + "Id": 73, + "Name": "Brand72", + "Products": [ + { + "Id": 7201, + "Name": "Product 72-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 73, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 74, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 7301, + "Name": "Product 73-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 74, + "Brand": { + "Id": 74, + "Name": "Brand73", + "Products": [ + { + "Id": 7302, + "Name": "Product 73-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 74, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 7302, + "Name": "Product 73-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 74, + "Brand": { + "Id": 74, + "Name": "Brand73", + "Products": [ + { + "Id": 7301, + "Name": "Product 73-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 74, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 75, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 7401, + "Name": "Product 74-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 75, + "Brand": { + "Id": 75, + "Name": "Brand74", + "Products": [ + { + "Id": 7402, + "Name": "Product 74-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 75, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 7402, + "Name": "Product 74-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 75, + "Brand": { + "Id": 75, + "Name": "Brand74", + "Products": [ + { + "Id": 7401, + "Name": "Product 74-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 75, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 76, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 7501, + "Name": "Product 75-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 76, + "Brand": { + "Id": 76, + "Name": "Brand75", + "Products": [ + { + "Id": 7502, + "Name": "Product 75-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 76, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 7502, + "Name": "Product 75-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 76, + "Brand": { + "Id": 76, + "Name": "Brand75", + "Products": [ + { + "Id": 7501, + "Name": "Product 75-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 76, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 77, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 7601, + "Name": "Product 76-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 77, + "Brand": { + "Id": 77, + "Name": "Brand76", + "Products": [ + { + "Id": 7602, + "Name": "Product 76-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 77, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 7602, + "Name": "Product 76-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 77, + "Brand": { + "Id": 77, + "Name": "Brand76", + "Products": [ + { + "Id": 7601, + "Name": "Product 76-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 77, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 78, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 7701, + "Name": "Product 77-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 78, + "Brand": { + "Id": 78, + "Name": "Brand77", + "Products": [ + { + "Id": 7702, + "Name": "Product 77-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 78, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 7702, + "Name": "Product 77-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 78, + "Brand": { + "Id": 78, + "Name": "Brand77", + "Products": [ + { + "Id": 7701, + "Name": "Product 77-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 78, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 79, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 7801, + "Name": "Product 78-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 79, + "Brand": { + "Id": 79, + "Name": "Brand78", + "Products": [ + { + "Id": 7802, + "Name": "Product 78-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 79, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 7802, + "Name": "Product 78-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 79, + "Brand": { + "Id": 79, + "Name": "Brand78", + "Products": [ + { + "Id": 7801, + "Name": "Product 78-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 79, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 80, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 7901, + "Name": "Product 79-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 80, + "Brand": { + "Id": 80, + "Name": "Brand79", + "Products": [ + { + "Id": 7902, + "Name": "Product 79-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 80, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 7902, + "Name": "Product 79-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 80, + "Brand": { + "Id": 80, + "Name": "Brand79", + "Products": [ + { + "Id": 7901, + "Name": "Product 79-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 80, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 81, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 8001, + "Name": "Product 80-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 81, + "Brand": { + "Id": 81, + "Name": "Brand80", + "Products": [ + { + "Id": 8002, + "Name": "Product 80-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 81, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 8002, + "Name": "Product 80-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 81, + "Brand": { + "Id": 81, + "Name": "Brand80", + "Products": [ + { + "Id": 8001, + "Name": "Product 80-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 81, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 82, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 8101, + "Name": "Product 81-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 82, + "Brand": { + "Id": 82, + "Name": "Brand81", + "Products": [ + { + "Id": 8102, + "Name": "Product 81-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 82, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 8102, + "Name": "Product 81-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 82, + "Brand": { + "Id": 82, + "Name": "Brand81", + "Products": [ + { + "Id": 8101, + "Name": "Product 81-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 82, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 83, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 8201, + "Name": "Product 82-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 83, + "Brand": { + "Id": 83, + "Name": "Brand82", + "Products": [ + { + "Id": 8202, + "Name": "Product 82-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 83, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 8202, + "Name": "Product 82-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 83, + "Brand": { + "Id": 83, + "Name": "Brand82", + "Products": [ + { + "Id": 8201, + "Name": "Product 82-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 83, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 84, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 8301, + "Name": "Product 83-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 84, + "Brand": { + "Id": 84, + "Name": "Brand83", + "Products": [ + { + "Id": 8302, + "Name": "Product 83-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 84, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 8302, + "Name": "Product 83-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 84, + "Brand": { + "Id": 84, + "Name": "Brand83", + "Products": [ + { + "Id": 8301, + "Name": "Product 83-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 84, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 85, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 8401, + "Name": "Product 84-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 85, + "Brand": { + "Id": 85, + "Name": "Brand84", + "Products": [ + { + "Id": 8402, + "Name": "Product 84-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 85, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 8402, + "Name": "Product 84-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 85, + "Brand": { + "Id": 85, + "Name": "Brand84", + "Products": [ + { + "Id": 8401, + "Name": "Product 84-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 85, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 86, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 8501, + "Name": "Product 85-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 86, + "Brand": { + "Id": 86, + "Name": "Brand85", + "Products": [ + { + "Id": 8502, + "Name": "Product 85-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 86, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 8502, + "Name": "Product 85-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 86, + "Brand": { + "Id": 86, + "Name": "Brand85", + "Products": [ + { + "Id": 8501, + "Name": "Product 85-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 86, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 87, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 8601, + "Name": "Product 86-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 87, + "Brand": { + "Id": 87, + "Name": "Brand86", + "Products": [ + { + "Id": 8602, + "Name": "Product 86-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 87, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 8602, + "Name": "Product 86-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 87, + "Brand": { + "Id": 87, + "Name": "Brand86", + "Products": [ + { + "Id": 8601, + "Name": "Product 86-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 87, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 88, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 8701, + "Name": "Product 87-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 88, + "Brand": { + "Id": 88, + "Name": "Brand87", + "Products": [ + { + "Id": 8702, + "Name": "Product 87-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 88, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 8702, + "Name": "Product 87-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 88, + "Brand": { + "Id": 88, + "Name": "Brand87", + "Products": [ + { + "Id": 8701, + "Name": "Product 87-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 88, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 89, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 8801, + "Name": "Product 88-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 89, + "Brand": { + "Id": 89, + "Name": "Brand88", + "Products": [ + { + "Id": 8802, + "Name": "Product 88-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 89, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 8802, + "Name": "Product 88-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 89, + "Brand": { + "Id": 89, + "Name": "Brand88", + "Products": [ + { + "Id": 8801, + "Name": "Product 88-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 89, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 90, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 8901, + "Name": "Product 89-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 90, + "Brand": { + "Id": 90, + "Name": "Brand89", + "Products": [ + { + "Id": 8902, + "Name": "Product 89-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 90, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 8902, + "Name": "Product 89-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 90, + "Brand": { + "Id": 90, + "Name": "Brand89", + "Products": [ + { + "Id": 8901, + "Name": "Product 89-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 90, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 91, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 9001, + "Name": "Product 90-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 91, + "Brand": { + "Id": 91, + "Name": "Brand90", + "Products": [ + { + "Id": 9002, + "Name": "Product 90-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 91, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 9002, + "Name": "Product 90-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 91, + "Brand": { + "Id": 91, + "Name": "Brand90", + "Products": [ + { + "Id": 9001, + "Name": "Product 90-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 91, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 92, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 9101, + "Name": "Product 91-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 92, + "Brand": { + "Id": 92, + "Name": "Brand91", + "Products": [ + { + "Id": 9102, + "Name": "Product 91-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 92, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 9102, + "Name": "Product 91-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 92, + "Brand": { + "Id": 92, + "Name": "Brand91", + "Products": [ + { + "Id": 9101, + "Name": "Product 91-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 92, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 93, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 9201, + "Name": "Product 92-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 93, + "Brand": { + "Id": 93, + "Name": "Brand92", + "Products": [ + { + "Id": 9202, + "Name": "Product 92-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 93, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 9202, + "Name": "Product 92-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 93, + "Brand": { + "Id": 93, + "Name": "Brand92", + "Products": [ + { + "Id": 9201, + "Name": "Product 92-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 93, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 94, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 9301, + "Name": "Product 93-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 94, + "Brand": { + "Id": 94, + "Name": "Brand93", + "Products": [ + { + "Id": 9302, + "Name": "Product 93-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 94, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 9302, + "Name": "Product 93-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 94, + "Brand": { + "Id": 94, + "Name": "Brand93", + "Products": [ + { + "Id": 9301, + "Name": "Product 93-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 94, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 95, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 9401, + "Name": "Product 94-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 95, + "Brand": { + "Id": 95, + "Name": "Brand94", + "Products": [ + { + "Id": 9402, + "Name": "Product 94-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 95, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 9402, + "Name": "Product 94-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 95, + "Brand": { + "Id": 95, + "Name": "Brand94", + "Products": [ + { + "Id": 9401, + "Name": "Product 94-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 95, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 96, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 9501, + "Name": "Product 95-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 96, + "Brand": { + "Id": 96, + "Name": "Brand95", + "Products": [ + { + "Id": 9502, + "Name": "Product 95-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 96, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 9502, + "Name": "Product 95-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 96, + "Brand": { + "Id": 96, + "Name": "Brand95", + "Products": [ + { + "Id": 9501, + "Name": "Product 95-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 96, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 97, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 9601, + "Name": "Product 96-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 97, + "Brand": { + "Id": 97, + "Name": "Brand96", + "Products": [ + { + "Id": 9602, + "Name": "Product 96-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 97, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 9602, + "Name": "Product 96-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 97, + "Brand": { + "Id": 97, + "Name": "Brand96", + "Products": [ + { + "Id": 9601, + "Name": "Product 96-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 97, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 98, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 9701, + "Name": "Product 97-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 98, + "Brand": { + "Id": 98, + "Name": "Brand97", + "Products": [ + { + "Id": 9702, + "Name": "Product 97-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 98, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 9702, + "Name": "Product 97-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 98, + "Brand": { + "Id": 98, + "Name": "Brand97", + "Products": [ + { + "Id": 9701, + "Name": "Product 97-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 98, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 99, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 9801, + "Name": "Product 98-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 99, + "Brand": { + "Id": 99, + "Name": "Brand98", + "Products": [ + { + "Id": 9802, + "Name": "Product 98-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 99, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 9802, + "Name": "Product 98-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 99, + "Brand": { + "Id": 99, + "Name": "Brand98", + "Products": [ + { + "Id": 9801, + "Name": "Product 98-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 99, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ], + "PageKey { Key = 100, PagingArgs = PagingArguments { First = 2, After = , Last = , Before = } }": [ + { + "Id": 9901, + "Name": "Product 99-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 100, + "Brand": { + "Id": 100, + "Name": "Brand99", + "Products": [ + { + "Id": 9902, + "Name": "Product 99-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 100, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 9902, + "Name": "Product 99-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 100, + "Brand": { + "Id": 100, + "Name": "Brand99", + "Products": [ + { + "Id": 9901, + "Name": "Product 99-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 100, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] + }, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } + ] +} +``` diff --git a/src/HotChocolate/Data/test/Data.EntityFramework.Tests/__snapshots__/PagingHelperTests.Fetch_First_2_Items.md b/src/HotChocolate/Data/test/Data.EntityFramework.Tests/__snapshots__/PagingHelperTests.Fetch_First_2_Items.md new file mode 100644 index 00000000000..f8d904438fa --- /dev/null +++ b/src/HotChocolate/Data/test/Data.EntityFramework.Tests/__snapshots__/PagingHelperTests.Fetch_First_2_Items.md @@ -0,0 +1,36 @@ +# Fetch_First_2_Items + +```json +[ + { + "Id": 1, + "Name": "Product 0-0", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 1, + "Brand": null, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 2, + "Name": "Product 0-1", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 1, + "Brand": null, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } +] +``` diff --git a/src/HotChocolate/Data/test/Data.EntityFramework.Tests/__snapshots__/PagingHelperTests.Fetch_First_2_Items_Second_Page.md b/src/HotChocolate/Data/test/Data.EntityFramework.Tests/__snapshots__/PagingHelperTests.Fetch_First_2_Items_Second_Page.md new file mode 100644 index 00000000000..97fd1633919 --- /dev/null +++ b/src/HotChocolate/Data/test/Data.EntityFramework.Tests/__snapshots__/PagingHelperTests.Fetch_First_2_Items_Second_Page.md @@ -0,0 +1,36 @@ +# Fetch_First_2_Items_Second_Page + +```json +[ + { + "Id": 11, + "Name": "Product 0-10", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 1, + "Brand": null, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 12, + "Name": "Product 0-11", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 1, + "Brand": null, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } +] +``` diff --git a/src/HotChocolate/Data/test/Data.EntityFramework.Tests/__snapshots__/PagingHelperTests.Fetch_First_2_Items_Third_Page.md b/src/HotChocolate/Data/test/Data.EntityFramework.Tests/__snapshots__/PagingHelperTests.Fetch_First_2_Items_Third_Page.md new file mode 100644 index 00000000000..e3b30a5f65c --- /dev/null +++ b/src/HotChocolate/Data/test/Data.EntityFramework.Tests/__snapshots__/PagingHelperTests.Fetch_First_2_Items_Third_Page.md @@ -0,0 +1,36 @@ +# Fetch_First_2_Items_Third_Page + +```json +[ + { + "Id": 13, + "Name": "Product 0-12", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 1, + "Brand": null, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 14, + "Name": "Product 0-13", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 1, + "Brand": null, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } +] +``` diff --git a/src/HotChocolate/Data/test/Data.EntityFramework.Tests/__snapshots__/PagingHelperTests.Fetch_Last_2_Items.md b/src/HotChocolate/Data/test/Data.EntityFramework.Tests/__snapshots__/PagingHelperTests.Fetch_Last_2_Items.md new file mode 100644 index 00000000000..d2f8163c2b5 --- /dev/null +++ b/src/HotChocolate/Data/test/Data.EntityFramework.Tests/__snapshots__/PagingHelperTests.Fetch_Last_2_Items.md @@ -0,0 +1,36 @@ +# Fetch_Last_2_Items + +```json +[ + { + "Id": 9999, + "Name": "Product 99-98", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 100, + "Brand": null, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 10000, + "Name": "Product 99-99", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 100, + "Brand": null, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } +] +``` diff --git a/src/HotChocolate/Data/test/Data.EntityFramework.Tests/__snapshots__/PagingHelperTests.Fetch_Last_2_Items_Before_Last_Page.md b/src/HotChocolate/Data/test/Data.EntityFramework.Tests/__snapshots__/PagingHelperTests.Fetch_Last_2_Items_Before_Last_Page.md new file mode 100644 index 00000000000..5b70d43b6a3 --- /dev/null +++ b/src/HotChocolate/Data/test/Data.EntityFramework.Tests/__snapshots__/PagingHelperTests.Fetch_Last_2_Items_Before_Last_Page.md @@ -0,0 +1,36 @@ +# Fetch_Last_2_Items_Before_Last_Page + +```json +[ + { + "Id": 9997, + "Name": "Product 99-96", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 100, + "Brand": null, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + }, + { + "Id": 9998, + "Name": "Product 99-97", + "Description": null, + "Price": 0.0, + "ImageFileName": null, + "TypeId": 1, + "Type": null, + "BrandId": 100, + "Brand": null, + "AvailableStock": 0, + "RestockThreshold": 0, + "MaxStockThreshold": 0, + "OnReorder": false + } +] +``` diff --git a/website/src/basic/legal/privacy-policy.md b/website/src/basic/legal/privacy-policy.md index 578a2025735..3f4c6fe1c7a 100644 --- a/website/src/basic/legal/privacy-policy.md +++ b/website/src/basic/legal/privacy-policy.md @@ -172,7 +172,7 @@ Where the disclosure of your personal information is solely subject to Australia ## Data Controller / Data Processor -The GDPR distinguishes between organisations that process personal information for their own purposes (known as “data controllers”) and organizations that process personal information on behalf of other organizations (known as “data processors”). We, ChilliCream Inc., located at the address provided in our Contact Us section, are a Data Controller with respect to the personal information you provide to us. +The GDPR distinguishes between organizations that process personal information for their own purposes (known as “data controllers”) and organizations that process personal information on behalf of other organizations (known as “data processors”). We, ChilliCream Inc., located at the address provided in our Contact Us section, are a Data Controller with respect to the personal information you provide to us. ## Legal Bases for Processing Your Personal Information @@ -214,7 +214,7 @@ We will ensure that any transfer of personal information from countries in the E Under California Civil Code Section 1798.83, if you live in California and your business relationship with us is mainly for personal, family, or household purposes, you may ask us about the information we release to other organizations for their marketing purposes. -To make such a request, please contact us using the details provided in this privacy policy with “Request for California privacy information” in the subject line. You may make this type of request once every calendar year. We will email you a list of categories of personal information we revealed to other organisations for their marketing purposes in the last calendar year, along with their names and addresses. Not all personal information shared in this way is covered by Section 1798.83 of the California Civil Code. +To make such a request, please contact us using the details provided in this privacy policy with “Request for California privacy information” in the subject line. You may make this type of request once every calendar year. We will email you a list of categories of personal information we revealed to other organizations for their marketing purposes in the last calendar year, along with their names and addresses. Not all personal information shared in this way is covered by Section 1798.83 of the California Civil Code. ## Do Not Track diff --git a/website/src/docs/bananacakepop/v2/apis/fusion.md b/website/src/docs/bananacakepop/v2/apis/fusion.md index dee22b07879..fa915c18099 100644 --- a/website/src/docs/bananacakepop/v2/apis/fusion.md +++ b/website/src/docs/bananacakepop/v2/apis/fusion.md @@ -340,7 +340,7 @@ services ## `BlobStorageCache` -This cache stores your data in Azure Blob Storage. +This cache stores your data in Azure Blob Storage. You need to install the `BananaCakePop.Services.Azure` package: