blob: 5a6028ceed07b33b4f1504edaae07616884867b1 [file] [log] [blame]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-61232409-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-61232409-1');
</script>
<!-- Yandex.Metrika counter -->
<script type="text/javascript" >
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
m[i].l=1*new Date();k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
(window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");
ym(72949126, "init", {
clickmap:true,
trackLinks:true,
accurateTrackBounce:true,
webvisor:true
});
</script>
<noscript><div><img src="https://mc.yandex.ru/watch/72949126" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
<!-- /Yandex.Metrika counter -->
<!-- Bugyard widget embed -->
<script type="text/javascript">!function(){if("function"!=typeof window.bugyard){var a=function(){a.c(arguments)};a.q=[],a.c=function(b){a.q.push(b)},window.bugyard=a;var b=document.createElement("script");b.setAttribute("data-bugyard","610961912c35ff001493163a"),b.setAttribute("async","async"),b.setAttribute("defer","defer"),b.setAttribute("src","https://widget.bugyard.io/bugyard.min.js"),document.getElementsByTagName("head")[0].appendChild(b)}}(); window.bugyard("hideButton"); </script>
<link rel="preload" href='/assets/js/code-tabs.js?1' as="script" crossorigin>
<link rel="preload" href='/assets/js/page-nav.js' as="script" crossorigin>
<link rel="preload" href='/assets/js/docs-menu.js?20201005' as="script" crossorigin>
<style>:root{--gg-red:#ec1c24;--gg-orange:#ec1c24;--gg-orange-dark:#bc440b;--gg-orange-filter:invert(47%) sepia(61%) saturate(1950%) hue-rotate(345deg) brightness(100%) contrast(95%);--gg-dark-gray:#333333;--orange-line-thickness:3px;--block-code-background:rgba(241, 241, 241, 20%);--inline-code-background:rgba(241, 241, 241, 90%);--padding-top:25px;--link-color:#ec1c24;--body-background:#fcfcfc}header{min-height:var(--header-height);background:#fff;box-shadow:0 4px 10px 0 #eee,0 0 4px 0 #d5d5d5;z-index:1}header>.container{display:grid;grid-template-columns:auto auto 1fr auto auto auto;grid-template-areas:'left-toggle home nav ver api search lang';grid-template-rows:40px;flex-direction:row;align-items:center;justify-content:flex-start;padding:12px 20px;max-width:1400px;margin:0 auto}header nav>ul{padding:0;margin:0;list-style:none;display:inherit}header .dropdown{display:none;position:fixed;top:calc(var(--header-height) - 12px);width:auto;background:#fff;box-shadow:0 4px 4px 0 rgba(0,0,0,.24),0 0 4px 0 rgba(0,0,0,.12);border-radius:4px;padding-top:10px;padding-bottom:12px;z-index:2}header .dropdown li{display:flex}header .dropdown a{color:grey!important;font-size:16px;padding-top:5px;padding-bottom:4px}header .menu{border:none;background:0 0;width:40px;height:40px;margin-right:12px;grid-area:left-toggle}header .menu img{width:18px;height:12px}header .search-close,header .top-nav-toggle{background:0 0;border:none;padding:0;width:36px;height:36px;display:inline-flex;align-items:center;justify-content:center;color:var(--gg-dark-gray);font-size:26px}header .search-toggle{grid-area:search}header .top-nav-toggle{grid-area:top-toggle}header .home{grid-area:home;margin-right:auto}header .home img{height:36px}header #api-docs{grid-area:api;margin:0;display:flex}header #api-docs .dropdown{padding:.5em 0}header #api-docs a{padding:9px 14px;color:var(--gg-dark-gray)!important;text-decoration:none;white-space:nowrap}header #api-docs .dropdown-item a{font-weight:400;display:block;width:100%;min-width:150px}header #lang-selector li{list-style:none;display:flex;padding:9px 14px}header #lang-selector li a{display:flex;color:#000;align-items:center}header #lang-selector li a span{font-size:10px;margin-left:5px}header #lang-selector li a img{width:25px}header #lang-selector li .dropdown{margin-left:-70px}header #lang-selector li .dropdown .dropdown-item{padding:0 1em;margin-bottom:8px}header #lang-selector li .dropdown .dropdown-item a span{font-size:14px}header .search{margin-left:auto;margin-right:20px;grid-area:search}header .search input[type=search]{color:var(--gg-dark-gray);background:rgba(255,255,255,.8);border:1px solid #ccc;padding:10px 15px;font-family:inherit;max-width:148px;height:37px;font-size:14px;-webkit-appearance:unset;appearance:unset}header #version-selector{list-style:none;grid-area:ver;line-height:28px;border-radius:0;margin-right:10px;border:none;color:var(--gg-dark-gray);padding:5px 16px 5px 10px;white-space:nowrap;font-size:14px;width:auto;text-align:right;box-sizing:border-box;text-align-last:right;-moz-appearance:none;-webkit-appearance:none;appearance:none;direction:rtl}header #version-selector option{direction:ltr}header>nav{grid-area:nav;font-size:18px;display:flex;flex-direction:row;margin:0 20px}header #lang-selector{grid-area:lang}header .search-close{margin-right:10px}@media (max-width:600px){header .search{margin-right:5px}header .search input[type=search]{max-width:110px}}header:not(.narrow-header) .search-close,header:not(.narrow-header) .top-nav-toggle{display:none}@media (max-width:670px){header>.container{grid-template-columns:auto 1fr auto;grid-template-areas:'left-toggle home search' 'ver api lang'}header #lang-selector li{justify-content:flex-end}}pre,pre.rouge{padding:8px 15px;background:var(--block-code-background)!important;border-radius:5px;border:1px solid #e5e5e5;overflow-x:auto;min-height:36px;line-height:18px;color:#545454}code{color:#545454}pre.rouge code{background:0 0!important}:not(pre)>code{background:var(--inline-code-background);padding:.1em .5em;background-clip:padding-box;border-radius:3px;color:#545454;font-size:90%}.listingblock .content{position:relative}.highlight{color:#586e75}.highlight .c1{color:#657b83}.highlight .nt{color:#b58900}.highlight .o{color:#93a1a1}.highlight .k{color:#6c71c4}.highlight .kt{color:#cb4b16}.highlight .s,.highlight .s1{color:#859900}.highlight .nc{color:#b58900}.highlight .na{color:#268bd2}body{font-family:'Open Sans',sans-serif}h1,h2{color:#000;font-weight:400;font-family:'Open Sans'}h1{font-size:36px;line-height:40px}a{text-decoration:none;color:var(--link-color)}section{color:#545454}.admonitionblock .icon .title{display:none}body{--header-height:64px;--promotion-bar-height:35px;--footer-height:104px;--footer-gap:60px;padding:0;margin:0;display:flex;flex-direction:column;min-height:100vh;background-color:var(--body-background);font-family:'Open Sans',sans-serif}body>section{flex:1}header{position:-webkit-sticky;position:sticky;top:0;z-index:2}*{box-sizing:border-box}@media (max-width:670px){body{--header-height:97px}}.left-nav{padding:10px 20px;width:289px;overflow-y:auto;top:calc(var(--header-height) + var(--promotion-bar-height));height:calc(100vh - var(--header-height) - var(--promotion-bar-height));font-family:'Open Sans';padding-top:var(--padding-top);background-color:var(--body-background)}.left-nav li{list-style:none}.left-nav a,.left-nav button{text-decoration:none;color:#757575;font-size:16px;display:inline-flex;width:100%;margin:2px 0;padding:.25em .375em;background:0 0;border:none;font:inherit;text-align:left}.left-nav a.active{color:var(--link-color)}.left-nav .nav-group{margin-left:6px;font-size:14px}.left-nav nav{border-left:2px solid #ddd;margin-bottom:5px}.left-nav nav.collapsed{display:none}.left-nav nav>li>a,.left-nav nav>li>button{padding-left:20px;text-align:left}.left-nav nav>li>a.active{border-left:var(--orange-line-thickness) solid var(--active-color);padding-left:calc(20px - var(--orange-line-thickness))}.left-nav nav.sub_pages{border:none}.left-nav nav.sub_pages a{padding-left:32px}.left-nav .state-indicator{margin-left:auto;margin-top:5px;width:6.2px;height:10px;flex:0 0 auto;filter:invert(49%) sepia(4%) saturate(5%) hue-rotate(23deg) brightness(92%) contrast(90%)}.left-nav button.expanded .state-indicator{transform:rotate(90deg)}.right-nav{width:289px;padding:12px 26px;overflow-y:auto;height:calc(100vh - var(--header-height));top:0;position:-webkit-sticky;position:sticky;display:flex;flex-direction:column;font-family:'Open sans';padding-top:var(--padding-top);background-color:#fff}.right-nav ul{list-style:none;padding:0;margin:0}.right-nav li{padding:0}.right-nav a{--border-width:0px;font-size:14px;color:#757575;padding-left:calc(15px * var(--nesting-level) + 8px - var(--border-width));margin:.3em 0;display:inline-block}.right-nav .sectlevel1{border-left:2px solid #ddd}.right-nav .sectlevel1{--nesting-level:0}.right-nav .sectlevel2{--nesting-level:1}.right-nav .sectlevel3{--nesting-level:2}@media (max-width:1200px){.right-nav{width:230px}}.right-nav footer{font-size:12px;padding:calc(var(--footer-gap) * .3) 0 5px;text-align:left;margin:auto 0 0}section.page-docs{display:grid;grid-template-columns:auto 1fr auto;grid-template-rows:100%;grid-template-areas:'left-nav content right-nav';line-height:20px;max-width:1440px;margin:auto;width:100%}section.page-docs>article{border-left:1px solid #eee;background-color:#fff;padding:0 50px 30px;grid-area:content;overflow:hidden;font-family:sans-serif;font-size:16px;color:#545454;line-height:1.6em}section.page-docs>article h1,section.page-docs>article h2{font-family:'Open Sans'}@media (max-width:800px){section.page-docs>article{padding-left:15px;padding-right:15px}}section.page-docs .edit-link{position:relative;top:10px;right:10px;float:right;padding-top:calc(var(--header-height) + var(--padding-top));margin-top:calc((-1 * var(--header-height)))}section.page-docs h1,section.page-docs h2{margin-bottom:0}section.page-docs h2[id]{margin-top:var(--margin-top);margin-bottom:calc(var(--margin-top) * .5);z-index:-1}section.page-docs .title{font-style:italic}section.page-docs h2[id]{--margin-top:1.2em}.left-nav{bottom:0;position:-webkit-sticky;position:sticky}.left-nav{grid-area:left-nav}.right-nav{grid-area:right-nav}.left-nav__overlay{display:none;background:rgba(0,0,0,.5);z-index:1;position:fixed;top:var(--header-height);bottom:0;left:0;right:0}@media (max-width:990px){body:not(.hide-left-nav) .left-nav__overlay{display:block}nav.left-nav{background:#fafafa;grid-area:left-nav;box-shadow:0 4px 4px 0 rgba(0,0,0,.24),0 0 4px 0 rgba(0,0,0,.12);min-height:calc(100vh - var(--header-height));max-height:calc(100vh - var(--header-height));position:fixed;bottom:0;top:var(--header-height);z-index:2}section.page-docs>article{grid-column-start:left-nav;grid-column-end:content;grid-row:content}}@media (max-width:800px){nav.right-nav{display:none}}:target:before{content:"";display:block;margin-top:calc(var(--header-height) * -1);height:var(--header-height);width:1px}@media (min-width:600px) and (max-width:900px){:target:before{content:"";display:block;width:1px;margin-top:-150px;height:150px}}
#header #promotion-bar { background-color: #333333; padding: 8px; }
#header #promotion-bar p { font-size: 14px; line-height: 1.4em; font-weight: 600; padding: 0; margin: 0; color: #f0f0f0; text-align: center;}
#header #promotion-bar p a { color: #FCB903; } </style>
<meta name="ignite-version" content="3.0.0-beta" />
<title>.NET LINQ Queries | Ignite Documentation</title>
<link rel="canonical" href="/docs/3.0.0-beta/thin-clients/linq" />
<META NAME="ROBOTS" CONTENT="NOINDEX" />
<link rel="shortcut icon" href="/favicon.ico">
<meta name='viewport' content='width=device-width, height=device-height, initial-scale=1.0, minimum-scale=1.0'>
<link rel="preload" as="style" href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;600;700&display=swap" />
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;600;700&display=swap" media="print" onload="this.media='all'">
<noscript>
<link href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;600;700&display=swap" rel="stylesheet">
</noscript>
<script>
// AnchorJS - v4.2.0 - 2019-01-01
// https://github.com/bryanbraun/anchorjs
// Copyright (c) 2019 Bryan Braun; Licensed MIT
!function(A,e){"use strict";"function"==typeof define&&define.amd?define([],e):"object"==typeof module&&module.exports?module.exports=e():(A.AnchorJS=e(),A.anchors=new A.AnchorJS)}(this,function(){"use strict";return function(A){function f(A){A.icon=A.hasOwnProperty("icon")?A.icon:"",A.visible=A.hasOwnProperty("visible")?A.visible:"hover",A.placement=A.hasOwnProperty("placement")?A.placement:"right",A.ariaLabel=A.hasOwnProperty("ariaLabel")?A.ariaLabel:"Anchor",A.class=A.hasOwnProperty("class")?A.class:"",A.base=A.hasOwnProperty("base")?A.base:"",A.truncate=A.hasOwnProperty("truncate")?Math.floor(A.truncate):64,A.titleText=A.hasOwnProperty("titleText")?A.titleText:""}function p(A){var e;if("string"==typeof A||A instanceof String)e=[].slice.call(document.querySelectorAll(A));else{if(!(Array.isArray(A)||A instanceof NodeList))throw new Error("The selector provided to AnchorJS was invalid.");e=[].slice.call(A)}return e}this.options=A||{},this.elements=[],f(this.options),this.isTouchDevice=function(){return!!("ontouchstart"in window||window.DocumentTouch&&document instanceof DocumentTouch)},this.add=function(A){var e,t,i,n,o,s,a,r,c,h,l,u,d=[];if(f(this.options),"touch"===(l=this.options.visible)&&(l=this.isTouchDevice()?"always":"hover"),A||(A="h2, h3, h4, h5, h6"),0===(e=p(A)).length)return this;for(function(){if(null===document.head.querySelector("style.anchorjs")){var A,e=document.createElement("style");e.className="anchorjs",e.appendChild(document.createTextNode("")),void 0===(A=document.head.querySelector('[rel="stylesheet"], style'))?document.head.appendChild(e):document.head.insertBefore(e,A),e.sheet.insertRule(" .anchorjs-link { opacity: 0; text-decoration: none; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }",e.sheet.cssRules.length),e.sheet.insertRule(" *:hover > .anchorjs-link, .anchorjs-link:focus { opacity: 1; }",e.sheet.cssRules.length),e.sheet.insertRule(" [data-anchorjs-icon]::after { content: attr(data-anchorjs-icon); }",e.sheet.cssRules.length),e.sheet.insertRule(' @font-face { font-family: "anchorjs-icons"; src: url(data:n/a;base64,AAEAAAALAIAAAwAwT1MvMg8yG2cAAAE4AAAAYGNtYXDp3gC3AAABpAAAAExnYXNwAAAAEAAAA9wAAAAIZ2x5ZlQCcfwAAAH4AAABCGhlYWQHFvHyAAAAvAAAADZoaGVhBnACFwAAAPQAAAAkaG10eASAADEAAAGYAAAADGxvY2EACACEAAAB8AAAAAhtYXhwAAYAVwAAARgAAAAgbmFtZQGOH9cAAAMAAAAAunBvc3QAAwAAAAADvAAAACAAAQAAAAEAAHzE2p9fDzz1AAkEAAAAAADRecUWAAAAANQA6R8AAAAAAoACwAAAAAgAAgAAAAAAAAABAAADwP/AAAACgAAA/9MCrQABAAAAAAAAAAAAAAAAAAAAAwABAAAAAwBVAAIAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAMCQAGQAAUAAAKZAswAAACPApkCzAAAAesAMwEJAAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAAAAAAAAAAAAAQAAg//0DwP/AAEADwABAAAAAAQAAAAAAAAAAAAAAIAAAAAAAAAIAAAACgAAxAAAAAwAAAAMAAAAcAAEAAwAAABwAAwABAAAAHAAEADAAAAAIAAgAAgAAACDpy//9//8AAAAg6cv//f///+EWNwADAAEAAAAAAAAAAAAAAAAACACEAAEAAAAAAAAAAAAAAAAxAAACAAQARAKAAsAAKwBUAAABIiYnJjQ3NzY2MzIWFxYUBwcGIicmNDc3NjQnJiYjIgYHBwYUFxYUBwYGIwciJicmNDc3NjIXFhQHBwYUFxYWMzI2Nzc2NCcmNDc2MhcWFAcHBgYjARQGDAUtLXoWOR8fORYtLTgKGwoKCjgaGg0gEhIgDXoaGgkJBQwHdR85Fi0tOAobCgoKOBoaDSASEiANehoaCQkKGwotLXoWOR8BMwUFLYEuehYXFxYugC44CQkKGwo4GkoaDQ0NDXoaShoKGwoFBe8XFi6ALjgJCQobCjgaShoNDQ0NehpKGgobCgoKLYEuehYXAAAADACWAAEAAAAAAAEACAAAAAEAAAAAAAIAAwAIAAEAAAAAAAMACAAAAAEAAAAAAAQACAAAAAEAAAAAAAUAAQALAAEAAAAAAAYACAAAAAMAAQQJAAEAEAAMAAMAAQQJAAIABgAcAAMAAQQJAAMAEAAMAAMAAQQJAAQAEAAMAAMAAQQJAAUAAgAiAAMAAQQJAAYAEAAMYW5jaG9yanM0MDBAAGEAbgBjAGgAbwByAGoAcwA0ADAAMABAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAH//wAP) format("truetype"); }',e.sheet.cssRules.length)}}(),t=document.querySelectorAll("[id]"),i=[].map.call(t,function(A){return A.id}),o=0;o<e.length;o++)if(this.hasAnchorJSLink(e[o]))d.push(o);else{if(e[o].hasAttribute("id"))n=e[o].getAttribute("id");else if(e[o].hasAttribute("data-anchor-id"))n=e[o].getAttribute("data-anchor-id");else{for(c=r=this.urlify(e[o].textContent),a=0;void 0!==s&&(c=r+"-"+a),a+=1,-1!==(s=i.indexOf(c)););s=void 0,i.push(c),e[o].setAttribute("id",c),n=c}n.replace(/-/g," "),(h=document.createElement("a")).className="anchorjs-link "+this.options.class,h.setAttribute("aria-label",this.options.ariaLabel),h.setAttribute("data-anchorjs-icon",this.options.icon),this.options.titleText&&(h.title=this.options.titleText),u=document.querySelector("base")?window.location.pathname+window.location.search:"",u=this.options.base||u,h.href=u+"#"+n,"always"===l&&(h.style.opacity="1"),""===this.options.icon&&(h.style.font="1em/1 anchorjs-icons","left"===this.options.placement&&(h.style.lineHeight="inherit")),"left"===this.options.placement?(h.style.position="absolute",h.style.marginLeft="-1em",h.style.paddingRight="0.5em",e[o].insertBefore(h,e[o].firstChild)):(h.style.paddingLeft="0.375em",e[o].appendChild(h))}for(o=0;o<d.length;o++)e.splice(d[o]-o,1);return this.elements=this.elements.concat(e),this},this.remove=function(A){for(var e,t,i=p(A),n=0;n<i.length;n++)(t=i[n].querySelector(".anchorjs-link"))&&(-1!==(e=this.elements.indexOf(i[n]))&&this.elements.splice(e,1),i[n].removeChild(t));return this},this.removeAll=function(){this.remove(this.elements)},this.urlify=function(A){return this.options.truncate||f(this.options),A.trim().replace(/\'/gi,"").replace(/[& +$,:;=?@"#{}|^~[`%!'<>\]\.\/\(\)\*\\\n\t\b\v]/g,"-").replace(/-{2,}/g,"-").substring(0,this.options.truncate).replace(/^-+|-+$/gm,"").toLowerCase()},this.hasAnchorJSLink=function(A){var e=A.firstChild&&-1<(" "+A.firstChild.className+" ").indexOf(" anchorjs-link "),t=A.lastChild&&-1<(" "+A.lastChild.className+" ").indexOf(" anchorjs-link ");return e||t||!1}}});
</script>
</head>
<body>
<header>
<!--#include virtual="/includes/promotion_banner.html" -->
<div class="container">
<button type='button' class='menu' title='Docs menu'>
<img src="/assets/images/menu-icon.svg" width="18" height="12" alt="menu icon" />
</button>
<div class='home'>
<a href="/" class='home' title='Apache Ignite home'>
<img src="/assets/images/apache_ignite_logo.svg" alt="Apache Ignite logo" width="103" height="36" >
</a>
</div>
<select id="version-selector">
<option value="3.0.0-beta">3.0.0-beta</option>
</select>
<nav id="api-docs"><ul>
<li><a href="#">APIs</a>
<nav class='dropdown'>
<ul>
<li class="dropdown-item"><a href="/releases/latest/javadoc/index.html">Java</a></li>
<li class="dropdown-item"><a href="/releases/latest/dotnetdoc/api/">C#/.NET</a></li>
<li class="dropdown-item"><a href="/releases/latest/cppdoc/index.html">C++</a></li>
</ul>
</nav>
</li>
<li><a href="#">Examples</a>
<nav class="dropdown">
<ul>
<li class="dropdown-item"><a href="https://github.com/apache/ignite/tree/master/examples" target="_blank" rel="noopener" title="Apache Ignite Java examples">Java</a></li>
<li class="dropdown-item"><a href="https://github.com/apache/ignite/tree/master/modules/platforms/dotnet/examples" target="_blank" rel="noopener" title="Apache Ignite C#/.NET examples">C#/.NET</a></li>
<li class="dropdown-item"><a href="https://github.com/apache/ignite/tree/master/modules/platforms/cpp/examples" target="_blank" rel="noopener" title="Apache Ignite C++ examples">C++</a></li>
<li class="dropdown-item"><a href="https://github.com/apache/ignite/tree/master/modules/platforms/python/examples" target="_blank" rel="noopener" title="Apache Ignite Python examples">Python</a></li>
<li class="dropdown-item"><a href="https://github.com/apache/ignite/tree/master/modules/platforms/nodejs/examples" target="_blank" rel="noopener" title="Apache Ignite NodeJS examples">NodeJS</a></li>
<li class="dropdown-item"><a href="https://github.com/apache/ignite/tree/master/modules/platforms/php/examples" target="_blank" rel="noopener" title="Apache Ignite PHP examples">PHP</a></li>
</ul>
</nav>
</li></ul>
</nav>
<form class='search'>
<button class="search-close" type='button'><img src='/assets/images/cancel.svg' alt="close" width="10" height="10" /></button>
<input type="search" placeholder="Search…" id="search-input">
</form>
<nav id="lang-selector"><ul>
<li><a href="#"><img src="/assets/images/icon_lang_en_75x75.jpg" alt="English language icon" width="25" height="25" /><span></span></a>
<nav class="dropdown">
<li class="dropdown-item"><a href="/docs/latest/" ><img src="/assets/images/icon_lang_en_75x75.jpg" alt="English language icon" width="25" height="25" /><span>English</span></a></li>
<li class="dropdown-item"><a href="https://www.ignite-service.cn/doc/java/" target="_blank" rel="noopener"><img src="/assets/images/icon_lang_cn_75x75.jpg" width="25" height="25" alt="Chinese language icon" /><span>Chinese</span></a></li>
</nav>
</li></ul>
</nav>
<button type='button' class='top-nav-toggle'></button>
</div>
</header>
<link rel="stylesheet" href="/assets/css/docs.css">
<section class='page-docs'>
<nav class='left-nav' data-swiftype-index='false'>
<li>
<a href="/docs/3.0.0-beta/index" class='' >About Apache Ignite 3</a>
</li>
<li>
<a href="/docs/3.0.0-beta/quick-start/getting-started-guide" class='' >Getting Started Guide</a>
</li>
<li>
<button type='button' class='group-toggle collapsed '>Installation<img class="state-indicator" src="/assets/images/left-nav-arrow.svg" width="6" height="10"></button>
<nav class='nav-group collapsed'>
<li>
<a href="/docs/3.0.0-beta/installation/installing-using-zip"
class=''
>Installing Using ZIP Archive</a>
</li>
<li>
<a href="/docs/3.0.0-beta/installation/installing-using-docker"
class=''
>Installing Using Docker</a>
</li>
<li>
<a href="/docs/3.0.0-beta/installation/deb-rpm"
class=''
>Installing DEB or RPM package</a>
</li>
</nav>
</li>
<li>
<a href="/docs/3.0.0-beta/ignite-cli-tool" class='' >Ignite CLI Tool</a>
</li>
<li>
<button type='button' class='group-toggle collapsed '>Working with SQL<img class="state-indicator" src="/assets/images/left-nav-arrow.svg" width="6" height="10"></button>
<nav class='nav-group collapsed'>
<li>
<a href="/docs/3.0.0-beta/sql/calcite-based-sql-engine"
class=''
>Introduction</a>
</li>
<li>
<a href="/docs/3.0.0-beta/sql/jdbc-driver"
class=''
>JDBC Driver</a>
</li>
<li>
<button
type='button'
class='collapsed '>ODBC Driver<img class="state-indicator" src="/assets/images/left-nav-arrow.svg" width="6" height="10"></button>
<nav class="sub_pages collapsed">
<li><a href="/docs/3.0.0-beta/sql/odbc/odbc-driver" class=''>ODBC Driver</a></li>
<li><a href="/docs/3.0.0-beta/sql/odbc/connection-string" class=''>Connection String</a></li>
<li><a href="/docs/3.0.0-beta/sql/odbc/querying-modifying-data" class=''>Querying and Modifying Data</a></li>
</nav>
</li>
<li>
<a href="/docs/3.0.0-beta/sql/java"
class=''
>Java API</a>
</li>
</nav>
</li>
<li>
<button type='button' class='group-toggle collapsed '>SQL Reference<img class="state-indicator" src="/assets/images/left-nav-arrow.svg" width="6" height="10"></button>
<nav class='nav-group collapsed'>
<li>
<a href="/docs/3.0.0-beta/sql-reference/ddl"
class=''
>Data Definition Language (DDL)</a>
</li>
<li>
<a href="/docs/3.0.0-beta/sql-reference/dml"
class=''
>Data Manipulation Language (DML)</a>
</li>
<li>
<a href="/docs/3.0.0-beta/sql-reference/distribution-zones"
class=''
>Distribution Zones</a>
</li>
<li>
<a href="/docs/3.0.0-beta/sql-reference/operators-and-functions"
class=''
>Supported Operators and Functions</a>
</li>
</nav>
</li>
<li>
<button type='button' class='group-toggle collapsed '>REST<img class="state-indicator" src="/assets/images/left-nav-arrow.svg" width="6" height="10"></button>
<nav class='nav-group collapsed'>
<li>
<a href="/docs/3.0.0-beta/rest/rest-api"
class=''
>Overview</a>
</li>
<li>
<a href="/docs/3.0.0-beta/rest/reference"
class=''
>Reference</a>
</li>
</nav>
</li>
<li>
<button type='button' class='group-toggle expanded '>Clients & Drivers<img class="state-indicator" src="/assets/images/left-nav-arrow.svg" width="6" height="10"></button>
<nav class='nav-group expanded'>
<li>
<a href="/docs/3.0.0-beta/thin-clients/index"
class=''
>Ignite Clients</a>
</li>
<li>
<a href="/docs/3.0.0-beta/thin-clients/linq"
class='active'
>.NET LINQ Queries</a>
</li>
</nav>
</li>
<li>
<a href="/docs/3.0.0-beta/compute/compute" class='' >Distributed Computing</a>
</li>
<li>
<a href="/docs/3.0.0-beta/config/data-region" class='' >Data Region Configuration</a>
</li>
<li>
<button type='button' class='group-toggle collapsed '>Storage Configuration<img class="state-indicator" src="/assets/images/left-nav-arrow.svg" width="6" height="10"></button>
<nav class='nav-group collapsed'>
<li>
<a href="/docs/3.0.0-beta/storage/persistent"
class=''
>Native Persistent Storage</a>
</li>
<li>
<a href="/docs/3.0.0-beta/storage/rocksdb"
class=''
>RocksDB Persistent Storage</a>
</li>
<li>
<a href="/docs/3.0.0-beta/storage/volatile"
class=''
>Volatile Storage</a>
</li>
</nav>
</li>
<li>
<a href="/docs/3.0.0-beta/binary-protocol" class='' >Binary Client Protocol</a>
</li>
<li>
<a href="/docs/3.0.0-beta/ssl-tls" class='' >SSL/TLS</a>
</li>
<li>
<a href="/docs/3.0.0-beta/rebalance" class='' >Data Rebalancing</a>
</li>
<li>
<a href="/docs/3.0.0-beta/transactions/performing-transactions" class='' >Performing Transactions</a>
</li>
<li>
<a href="/docs/3.0.0-beta/table-views" class='' >Table Views</a>
</li>
<li>
<a href="/docs/3.0.0-beta/handling-exceptions" class='' >Handling Exceptions</a>
</li>
<li>
<a href="/docs/3.0.0-beta/glossary/glossary" class='' >Glossary</a>
</li>
</nav>
<div class="left-nav__overlay"></div>
<article data-swiftype-index='true'>
<a class='edit-link' href="https://github.com/apache/ignite-3/tree/main/docs/_docs/thin-clients/linq.adoc" target="_blank">Edit</a>
<h1>.NET LINQ Queries</h1>
<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>Apache Ignite .NET client provides LINQ support that is integrated with Ignite SQL APIs. You can avoid working with SQL syntax directly and write queries in C# with LINQ. C# LINQ expressions are then translated into Ignite-specific SQL. For example, the following two snippets achieve the same result:</p>
</div>
<code-tabs><code-tab data-tab='LINQ'><div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="csharp"><span class="kt">var</span> <span class="n">table</span> <span class="p">=</span> <span class="k">await</span> <span class="n">Client</span><span class="p">.</span><span class="n">Tables</span><span class="p">.</span><span class="nf">GetTableAsync</span><span class="p">(</span><span class="s">"TBL1"</span><span class="p">);</span>
<span class="n">IQueryable</span><span class="p">&lt;</span><span class="n">Poco</span><span class="p">&gt;</span> <span class="n">query</span> <span class="p">=</span> <span class="n">table</span><span class="p">!.</span><span class="n">GetRecordView</span><span class="p">&lt;</span><span class="n">Poco</span><span class="p">&gt;().</span><span class="nf">AsQueryable</span><span class="p">()</span>
<span class="p">.</span><span class="nf">Where</span><span class="p">(</span><span class="n">x</span> <span class="p">=&gt;</span> <span class="n">x</span><span class="p">.</span><span class="n">Key</span> <span class="p">&gt;</span> <span class="m">3</span><span class="p">)</span>
<span class="p">.</span><span class="nf">OrderBy</span><span class="p">(</span><span class="n">x</span> <span class="p">=&gt;</span> <span class="n">x</span><span class="p">.</span><span class="n">Key</span><span class="p">);</span>
<span class="n">List</span><span class="p">&lt;</span><span class="n">Poco</span><span class="p">&gt;</span> <span class="n">queryResults</span> <span class="p">=</span> <span class="k">await</span> <span class="n">query</span><span class="p">.</span><span class="nf">ToListAsync</span><span class="p">();</span></code></pre>
</div>
</div></code-tab><code-tab data-tab='SQL'><div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="csharp"><span class="kt">var</span> <span class="n">query</span> <span class="p">=</span> <span class="s">"select KEY, VAL from PUBLIC.TBL1 where (KEY &gt; ?) order by KEY asc"</span><span class="p">;</span>
<span class="k">await</span> <span class="k">using</span> <span class="nn">IResultSet</span><span class="p">&lt;</span><span class="n">IIgniteTuple</span><span class="p">&gt;</span> <span class="n">resultSet</span> <span class="p">=</span> <span class="k">await</span> <span class="n">Client</span><span class="p">.</span><span class="n">Sql</span><span class="p">.</span>
<span class="nf">ExecuteAsync</span><span class="p">(</span><span class="n">transaction</span><span class="p">:</span> <span class="k">null</span><span class="p">,</span> <span class="n">query</span><span class="p">,</span> <span class="m">3</span><span class="p">);</span>
<span class="kt">var</span> <span class="n">queryResults</span> <span class="p">=</span> <span class="k">new</span> <span class="n">List</span><span class="p">&lt;</span><span class="n">Poco</span><span class="p">&gt;();</span>
<span class="k">await</span> <span class="k">foreach</span> <span class="p">(</span><span class="n">IIgniteTuple</span> <span class="n">row</span> <span class="k">in</span> <span class="n">resultSet</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">queryResults</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="k">new</span> <span class="n">Poco</span> <span class="p">{</span> <span class="n">Key</span> <span class="p">=</span> <span class="p">(</span><span class="kt">long</span><span class="p">)</span><span class="n">row</span><span class="p">[</span><span class="m">0</span><span class="p">]!,</span> <span class="n">Val</span> <span class="p">=</span> <span class="p">(</span><span class="kt">string</span><span class="p">?)</span><span class="n">row</span><span class="p">[</span><span class="m">1</span><span class="p">]</span> <span class="p">});</span>
<span class="p">}</span></code></pre>
</div>
</div></code-tab></code-tabs>
<div class="paragraph">
<p>LINQ has the following advantages over SQL:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Queries are strongly typed and checked at compilation;</p>
</li>
<li>
<p>It is easier to write and maintain with IDE support (auto-completion, navigation, find usages);</p>
</li>
<li>
<p>LINQ is refactoring-friendly: rename a column and all queries are updated at once;</p>
</li>
<li>
<p>Ignite-specific SQL knowledge is not required, and most C# developers are already familiar with LINQ;</p>
</li>
<li>
<p>LINQ is safe against SQL injections;</p>
</li>
<li>
<p>Results are mapped to types naturally.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>In real-world scenarios the performance of Apache Ignite LINQ queries is on par with equivalent SQL queries.
However, a small overhead still exists (due to query translation), and your mileage may vary depending on the query complexity, so it is recommended to measure the performance of your queries.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="getting-started-with-linq">Getting Started With LINQ</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Here is how you can create a simple table in Apache Ignite:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Create a table:</p>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="csharp"><span class="k">await</span> <span class="n">Client</span><span class="p">.</span><span class="n">Sql</span><span class="p">.</span><span class="nf">ExecuteAsync</span><span class="p">(</span>
<span class="k">null</span><span class="p">,</span> <span class="s">@"CREATE TABLE PUBLIC.PERSON (NAME VARCHAR PRIMARY KEY, AGE INT)"</span><span class="p">);</span></code></pre>
</div>
</div>
</li>
<li>
<p>Define the classes (or records) that represent tables:</p>
<div class="ulist">
<ul>
<li>
<p>Member names should match column names (case-insensitive).</p>
</li>
<li>
<p>If a column name is not a valid C# identifier, use <code>[Column("name")]</code> attribute to specify the name.</p>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="csharp"><span class="k">public</span> <span class="k">record</span> <span class="nc">Person</span><span class="p">(</span><span class="kt">string</span> <span class="n">Name</span><span class="p">,</span> <span class="kt">int</span> <span class="n">Age</span><span class="p">,</span> <span class="kt">string</span> <span class="n">Address</span><span class="p">,</span> <span class="kt">string</span> <span class="n">Status</span><span class="p">);</span></code></pre>
</div>
</div>
</li>
</ul>
</div>
</li>
<li>
<p>Obtain a table reference:</p>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="csharp"><span class="n">ITable</span> <span class="n">table</span> <span class="p">=</span> <span class="k">await</span> <span class="n">Client</span><span class="p">.</span><span class="n">Tables</span><span class="p">.</span><span class="nf">GetTableAsync</span><span class="p">(</span><span class="s">"PERSON"</span><span class="p">);</span></code></pre>
</div>
</div>
</li>
<li>
<p>Use the <code>GetRecordView&lt;T&gt;()</code> method to get a typed view of the table:</p>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="csharp"><span class="n">IRecordView</span><span class="p">&lt;</span><span class="n">Person</span><span class="p">&gt;</span> <span class="n">view</span> <span class="p">=</span> <span class="n">table</span><span class="p">.</span><span class="n">GetRecordView</span><span class="p">&lt;</span><span class="n">Person</span><span class="p">&gt;();</span></code></pre>
</div>
</div>
</li>
<li>
<p>Use <code>AsQueryable()</code> to perform LINQ queries on <code>IRecordView&lt;T&gt;</code>.</p>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="csharp"><span class="n">List</span><span class="p">&lt;</span><span class="kt">string</span><span class="p">&gt;</span> <span class="n">names</span> <span class="p">=</span> <span class="k">await</span> <span class="n">view</span><span class="p">.</span><span class="nf">AsQueryable</span><span class="p">()</span>
<span class="p">.</span><span class="nf">Where</span><span class="p">(</span><span class="n">x</span> <span class="p">=&gt;</span> <span class="n">x</span><span class="p">.</span><span class="n">Age</span> <span class="p">&gt;</span> <span class="m">30</span><span class="p">)</span>
<span class="p">.</span><span class="nf">Select</span><span class="p">(</span><span class="n">x</span> <span class="p">=&gt;</span> <span class="n">x</span><span class="p">.</span><span class="n">Name</span><span class="p">)</span>
<span class="p">.</span><span class="nf">ToListAsync</span><span class="p">();</span></code></pre>
</div>
</div>
</li>
</ol>
</div>
</div>
</div>
<div class="sect1">
<h2 id="using-linq">Using LINQ</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="inspecting-generated-sql">Inspecting Generated SQL</h3>
<div class="paragraph">
<p>Viewing generated SQL is useful for debugging and performance tuning. There are two ways to do it:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>IgniteQueryableExtensions.ToQueryString()</code> extension method:</p>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="csharp"><span class="n">IQueryable</span><span class="p">&lt;</span><span class="n">Person</span><span class="p">&gt;</span> <span class="n">query</span> <span class="p">=</span> <span class="n">table</span><span class="p">.</span><span class="n">GetRecordView</span><span class="p">&lt;</span><span class="n">Person</span><span class="p">&gt;()</span>
<span class="p">.</span><span class="nf">AsQueryable</span><span class="p">()</span>
<span class="p">.</span><span class="nf">Where</span><span class="p">(</span><span class="n">x</span> <span class="p">=&gt;</span> <span class="n">x</span><span class="p">.</span><span class="n">Age</span> <span class="p">&gt;</span> <span class="m">30</span><span class="p">);</span>
<span class="kt">string</span> <span class="n">sql</span> <span class="p">=</span> <span class="n">query</span><span class="p">.</span><span class="nf">ToQueryString</span><span class="p">();</span></code></pre>
</div>
</div>
</li>
<li>
<p>Debug logging:</p>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="csharp"><span class="kt">var</span> <span class="n">cfg</span> <span class="p">=</span> <span class="k">new</span> <span class="n">IgniteClientConfiguration</span>
<span class="p">{</span>
<span class="n">Logger</span> <span class="p">=</span> <span class="k">new</span> <span class="n">ConsoleLogger</span> <span class="p">{</span> <span class="n">MinLevel</span> <span class="p">=</span> <span class="n">LogLevel</span><span class="p">.</span><span class="n">Debug</span> <span class="p">},</span>
<span class="p">...</span>
<span class="p">};</span>
<span class="k">using</span> <span class="nn">var</span> <span class="n">client</span> <span class="p">=</span> <span class="n">IgniteClient</span><span class="p">.</span><span class="nf">StartAsync</span><span class="p">(</span><span class="n">cfg</span><span class="p">);</span>
<span class="p">...</span></code></pre>
</div>
</div>
</li>
</ul>
</div>
<div class="paragraph">
<p>All generated SQL will be logged with <code>Debug</code> level to the specified logger.</p>
</div>
</div>
<div class="sect2">
<h3 id="transactions">Transactions</h3>
<div class="paragraph">
<p>Transaction can be passed to the LINQ provider by using the <code>AsQueryeable</code> parameter:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="csharp"><span class="k">await</span> <span class="k">using</span> <span class="nn">var</span> <span class="n">tx</span> <span class="p">=</span> <span class="k">await</span> <span class="n">client</span><span class="p">.</span><span class="n">Transactions</span><span class="p">.</span><span class="nf">BeginAsync</span><span class="p">();</span>
<span class="kt">var</span> <span class="n">view</span> <span class="p">=</span> <span class="p">(</span><span class="k">await</span> <span class="n">client</span><span class="p">.</span><span class="n">Tables</span><span class="p">.</span><span class="nf">GetTableAsync</span><span class="p">(</span><span class="s">"person"</span><span class="p">))!.</span><span class="n">GetRecordView</span><span class="p">&lt;</span><span class="n">Person</span><span class="p">&gt;();</span>
<span class="n">pocoView</span><span class="p">.</span><span class="nf">AsQueryable</span><span class="p">(</span><span class="n">tx</span><span class="p">)...;</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="custom-query-options">Custom Query Options</h3>
<div class="paragraph">
<p>Custom query options (timeout, page size) can be specified by using the second <code>AsQueryable</code> parameter with <code>QueryableOptions</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="csharp"><span class="kt">var</span> <span class="n">options</span> <span class="p">=</span> <span class="k">new</span> <span class="n">QueryableOptions</span>
<span class="p">{</span>
<span class="n">PageSize</span> <span class="p">=</span> <span class="m">512</span><span class="p">,</span>
<span class="n">Timeout</span> <span class="p">=</span> <span class="n">TimeSpan</span><span class="p">.</span><span class="nf">FromSeconds</span><span class="p">(</span><span class="m">30</span><span class="p">)</span>
<span class="p">};</span>
<span class="n">table</span><span class="p">.</span><span class="n">GetRecordView</span><span class="p">&lt;</span><span class="n">Person</span><span class="p">&gt;().</span><span class="nf">AsQueryable</span><span class="p">(</span><span class="n">options</span><span class="p">:</span> <span class="n">options</span><span class="p">)...;</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="result-materialization">Result Materialization</h3>
<div class="paragraph">
<p>Materialization is the process of converting query results (<code>IQueryable&lt;T&gt;</code>) into an object or a collection of objects.</p>
</div>
<div class="paragraph">
<p>LINQ is lazy. Nothing happens (no network calls, no SQL translation) until the query is materialized.
For example, the following code only constructs an expression, but does not execute anything:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="csharp"><span class="n">IQueryable</span><span class="p">&lt;</span><span class="n">Person</span><span class="p">&gt;</span> <span class="n">query</span> <span class="p">=</span> <span class="n">table</span><span class="p">!.</span><span class="n">GetRecordView</span><span class="p">&lt;</span><span class="n">Person</span><span class="p">&gt;().</span><span class="nf">AsQueryable</span><span class="p">()</span>
<span class="p">.</span><span class="nf">Where</span><span class="p">(</span><span class="n">x</span> <span class="p">=&gt;</span> <span class="n">x</span><span class="p">.</span><span class="n">Key</span> <span class="p">&gt;</span> <span class="m">3</span><span class="p">)</span>
<span class="p">.</span><span class="nf">OrderBy</span><span class="p">(</span><span class="n">x</span> <span class="p">=&gt;</span> <span class="n">x</span><span class="p">.</span><span class="n">Key</span><span class="p">);</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Query execution and materialization can be triggered in multiple ways:</p>
</div>
<div class="sect3">
<h4 id="iteration">Iteration</h4>
<div class="paragraph">
<p>You can iterate through query results by using <code>foreach</code> statement, or asynchronously by using the <code>AsAsyncEnumerable</code> method:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="csharp"><span class="k">foreach</span> <span class="p">(</span><span class="kt">var</span> <span class="n">person</span> <span class="k">in</span> <span class="n">query</span><span class="p">)</span> <span class="p">{</span> <span class="p">...</span> <span class="p">}</span>
<span class="k">await</span> <span class="k">foreach</span> <span class="p">(</span><span class="kt">var</span> <span class="n">person</span> <span class="k">in</span> <span class="n">query</span><span class="p">.</span><span class="nf">AsAsyncEnumerable</span><span class="p">())</span> <span class="p">{</span> <span class="p">...</span> <span class="p">}</span></code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="converting-to-collections">Converting to Collections</h4>
<div class="paragraph">
<p>You can convert queries to collections by using the <code>ToList</code> and <code>ToDictionary</code> methods, or <code>ToListAsync</code> and <code>ToDictionaryAsync</code> methods to do it asynchronously:</p>
</div>
<code-tabs><code-tab data-tab='Synchronous'><div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="csharp"><span class="n">List</span><span class="p">&lt;</span><span class="n">Person</span><span class="p">&gt;</span> <span class="n">list</span> <span class="p">=</span> <span class="n">query</span><span class="p">.</span><span class="nf">ToList</span><span class="p">();</span>
<span class="n">Dictionary</span><span class="p">&lt;</span><span class="kt">string</span><span class="p">,</span> <span class="kt">int</span><span class="p">&gt;</span> <span class="n">dict</span> <span class="p">=</span> <span class="n">query</span><span class="p">.</span><span class="nf">ToDictionary</span><span class="p">(</span><span class="n">x</span> <span class="p">=&gt;</span> <span class="n">x</span><span class="p">.</span><span class="n">Name</span><span class="p">,</span> <span class="n">x</span> <span class="p">=&gt;</span> <span class="n">x</span><span class="p">.</span><span class="n">Age</span><span class="p">);</span></code></pre>
</div>
</div></code-tab><code-tab data-tab='Asynchronous'><div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="csharp"><span class="n">List</span><span class="p">&lt;</span><span class="n">Person</span><span class="p">&gt;</span> <span class="n">list</span> <span class="p">=</span> <span class="k">await</span> <span class="n">query</span><span class="p">.</span><span class="nf">ToListAsync</span><span class="p">();</span>
<span class="n">Dictionary</span><span class="p">&lt;</span><span class="kt">string</span><span class="p">,</span> <span class="kt">int</span><span class="p">&gt;</span> <span class="n">dict</span> <span class="p">=</span> <span class="k">await</span> <span class="n">query</span><span class="p">.</span>
<span class="nf">ToDictionaryAsync</span><span class="p">(</span><span class="n">x</span> <span class="p">=&gt;</span> <span class="n">x</span><span class="p">.</span><span class="n">Name</span><span class="p">,</span> <span class="n">x</span> <span class="p">=&gt;</span> <span class="n">x</span><span class="p">.</span><span class="n">Age</span><span class="p">);</span></code></pre>
</div>
</div></code-tab></code-tabs>
</div>
<div class="sect3">
<h4 id="ignite-specific-iresultset">Ignite-specific IResultSet</h4>
<div class="paragraph">
<p>Underlying <code>IResultSet</code> can be obtained by using the <code>IgniteQueryableExtensions.ToResultSetAsync()</code> extension method:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="csharp"><span class="k">await</span> <span class="k">using</span> <span class="nn">IResultSet</span><span class="p">&lt;</span><span class="n">Person</span><span class="p">&gt;</span> <span class="n">resultSet</span> <span class="p">=</span> <span class="k">await</span> <span class="n">query</span><span class="p">.</span><span class="nf">ToResultSetAsync</span><span class="p">();</span>
<span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="n">resultSet</span><span class="p">.</span><span class="n">Metadata</span><span class="p">);</span>
<span class="kt">var</span> <span class="n">rows</span> <span class="p">=</span> <span class="n">resultSet</span><span class="p">.</span><span class="nf">CollectAsync</span><span class="p">(...);</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Obtaining <code>IResultSet</code> can be useful for access to metadata and <code>CollectAsync</code> method, which provides more control over result materialization.</p>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="supported-linq-features">Supported LINQ Features</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="projection">Projection</h3>
<div class="paragraph">
<p>Projection is the process of converting query results into a different type.
Among other things, projections are used to select a subset of columns.</p>
</div>
<div class="paragraph">
<p>For example, <code>Person</code> table may have many columns, but we only need <code>Name</code> and <code>Age</code>.</p>
</div>
<div class="ulist">
<ul>
<li>
<p>First, create a projection class:</p>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="csharp"><span class="k">public</span> <span class="k">record</span> <span class="nc">PersonInfo</span><span class="p">(</span><span class="kt">string</span> <span class="n">Name</span><span class="p">,</span> <span class="kt">int</span> <span class="n">Age</span><span class="p">);</span></code></pre>
</div>
</div>
</li>
<li>
<p>Then, use <code>Select</code> to project query results:</p>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="csharp"><span class="n">List</span><span class="p">&lt;</span><span class="n">PersonInfo</span><span class="p">&gt;</span> <span class="n">result</span> <span class="p">=</span> <span class="n">query</span>
<span class="p">.</span><span class="nf">Select</span><span class="p">(</span><span class="n">x</span> <span class="p">=&gt;</span> <span class="k">new</span> <span class="nf">PersonInfo</span><span class="p">(</span><span class="n">x</span><span class="p">.</span><span class="n">Name</span><span class="p">,</span> <span class="n">x</span><span class="p">.</span><span class="n">Age</span><span class="p">))</span>
<span class="p">.</span><span class="nf">ToList</span><span class="p">();</span></code></pre>
</div>
</div>
</li>
</ul>
</div>
<div class="paragraph">
<p>Resulting SQL will select only those two columns, avoiding overfetching
(a common issue that happens when ORM-generated query includes all table columns, but only a few of them are needed by the business logic).</p>
</div>
<div class="paragraph">
<p>Ignite also supports anonymous type projections:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="csharp"><span class="kt">var</span> <span class="n">result</span> <span class="p">=</span> <span class="n">query</span><span class="p">.</span><span class="nf">Select</span><span class="p">(</span><span class="n">x</span> <span class="p">=&gt;</span> <span class="k">new</span> <span class="p">{</span> <span class="n">x</span><span class="p">.</span><span class="n">Name</span><span class="p">,</span> <span class="n">x</span><span class="p">.</span><span class="n">Age</span> <span class="p">}).</span><span class="nf">ToList</span><span class="p">();</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="inner-joins">Inner Joins</h3>
<div class="paragraph">
<p>Use the standard <code>Join</code> method to perform joins on other tables:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="csharp"><span class="kt">var</span> <span class="n">customerQuery</span> <span class="p">=</span> <span class="n">customerTable</span><span class="p">.</span><span class="n">GetRecordView</span><span class="p">&lt;</span><span class="n">Customer</span><span class="p">&gt;().</span><span class="nf">AsQueryable</span><span class="p">();</span>
<span class="kt">var</span> <span class="n">orderQuery</span> <span class="p">=</span> <span class="n">orderTable</span><span class="p">.</span><span class="n">GetRecordView</span><span class="p">&lt;</span><span class="n">Order</span><span class="p">&gt;().</span><span class="nf">AsQueryable</span><span class="p">();</span>
<span class="kt">var</span> <span class="n">ordersByCustomer</span> <span class="p">=</span> <span class="n">customerQuery</span>
<span class="p">.</span><span class="nf">Join</span><span class="p">(</span><span class="n">orderQuery</span><span class="p">,</span>
<span class="n">cust</span> <span class="p">=&gt;</span> <span class="n">cust</span><span class="p">.</span><span class="n">Id</span><span class="p">,</span>
<span class="n">order</span> <span class="p">=&gt;</span> <span class="n">order</span><span class="p">.</span><span class="n">CustId</span><span class="p">,</span>
<span class="p">(</span><span class="n">cust</span><span class="p">,</span> <span class="n">order</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="k">new</span> <span class="p">{</span> <span class="n">cust</span><span class="p">.</span><span class="n">Name</span><span class="p">,</span> <span class="n">order</span><span class="p">.</span><span class="n">Amount</span> <span class="p">})</span>
<span class="p">.</span><span class="nf">ToList</span><span class="p">();</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="outer-joins">Outer Joins</h3>
<div class="paragraph">
<p>Outer joins are supported through the <code>DefaultIfEmpty</code> method.
For example, not every book in a library is borrowed by a student, so a left outer join is used to retrieve all books and their current borrowers (if any):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="csharp"><span class="kt">var</span> <span class="n">bookQuery</span> <span class="p">=</span> <span class="n">bookTable</span><span class="p">.</span><span class="n">GetRecordView</span><span class="p">&lt;</span><span class="n">Book</span><span class="p">&gt;().</span><span class="nf">AsQueryable</span><span class="p">();</span>
<span class="kt">var</span> <span class="n">studentQuery</span> <span class="p">=</span> <span class="n">studentTable</span><span class="p">.</span><span class="n">GetRecordView</span><span class="p">&lt;</span><span class="n">Student</span><span class="p">&gt;().</span><span class="nf">AsQueryable</span><span class="p">();</span>
<span class="kt">var</span> <span class="n">booksWithStudents</span> <span class="p">=</span> <span class="n">bookQuery</span>
<span class="p">.</span><span class="nf">Join</span><span class="p">(</span><span class="n">studentQuery</span><span class="p">.</span><span class="nf">DefaultIfEmpty</span><span class="p">(),</span>
<span class="n">book</span> <span class="p">=&gt;</span> <span class="n">book</span><span class="p">.</span><span class="n">StudentId</span><span class="p">,</span>
<span class="n">student</span> <span class="p">=&gt;</span> <span class="n">student</span><span class="p">.</span><span class="n">Id</span><span class="p">,</span>
<span class="p">(</span><span class="n">book</span><span class="p">,</span> <span class="n">student</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="k">new</span> <span class="p">{</span> <span class="n">book</span><span class="p">.</span><span class="n">Title</span><span class="p">,</span> <span class="n">student</span><span class="p">.</span><span class="n">Name</span> <span class="p">})</span>
<span class="p">.</span><span class="nf">ToList</span><span class="p">();</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="grouping">Grouping</h3>
<div class="paragraph">
<p>Grouping is supported through <code>GroupBy</code> method. This is equivalent to SQL GROUP BY operator. You can get both single and multiple columns in your queries. When working with multiple columns, use anonymous type:</p>
</div>
<code-tabs><code-tab data-tab='Single Column'><div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="csharp"><span class="kt">var</span> <span class="n">bookCountByAuthor</span> <span class="p">=</span> <span class="n">bookTable</span><span class="p">.</span><span class="n">GetRecordView</span><span class="p">&lt;</span><span class="n">Book</span><span class="p">&gt;().</span><span class="nf">AsQueryable</span><span class="p">()</span>
<span class="p">.</span><span class="nf">GroupBy</span><span class="p">(</span><span class="n">book</span> <span class="p">=&gt;</span> <span class="n">book</span><span class="p">.</span><span class="n">Author</span><span class="p">)</span>
<span class="p">.</span><span class="nf">Select</span><span class="p">(</span><span class="n">grp</span> <span class="p">=&gt;</span> <span class="k">new</span> <span class="p">{</span> <span class="n">Author</span> <span class="p">=</span> <span class="n">grp</span><span class="p">.</span><span class="n">Key</span><span class="p">,</span> <span class="n">Count</span> <span class="p">=</span> <span class="n">x</span><span class="p">.</span><span class="nf">Count</span><span class="p">()</span> <span class="p">})</span>
<span class="p">.</span><span class="nf">ToList</span><span class="p">();</span></code></pre>
</div>
</div></code-tab><code-tab data-tab='Multiple Columns'><div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="csharp"><span class="kt">var</span> <span class="n">bookCountByAuthorAndYear</span> <span class="p">=</span> <span class="n">bookTable</span><span class="p">.</span><span class="n">GetRecordView</span><span class="p">&lt;</span><span class="n">Book</span><span class="p">&gt;().</span><span class="nf">AsQueryable</span><span class="p">()</span>
<span class="p">.</span><span class="nf">GroupBy</span><span class="p">(</span><span class="n">book</span> <span class="p">=&gt;</span> <span class="k">new</span> <span class="p">{</span> <span class="n">book</span><span class="p">.</span><span class="n">Author</span><span class="p">,</span> <span class="n">book</span><span class="p">.</span><span class="n">Year</span> <span class="p">})</span>
<span class="p">.</span><span class="nf">Select</span><span class="p">(</span><span class="n">grp</span> <span class="p">=&gt;</span> <span class="k">new</span> <span class="p">{</span> <span class="n">Author</span> <span class="p">=</span> <span class="n">grp</span><span class="p">.</span><span class="n">Key</span><span class="p">.</span><span class="n">Author</span><span class="p">,</span>
<span class="n">Year</span> <span class="p">=</span> <span class="n">grp</span><span class="p">.</span><span class="n">Key</span><span class="p">.</span><span class="n">Year</span><span class="p">,</span>
<span class="n">Count</span> <span class="p">=</span> <span class="n">x</span><span class="p">.</span><span class="nf">Count</span><span class="p">()</span> <span class="p">})</span>
<span class="p">.</span><span class="nf">ToList</span><span class="p">();</span></code></pre>
</div>
</div></code-tab></code-tabs>
<div class="paragraph">
<p>Aggregate functions <code>Count</code>, <code>Sum</code>, <code>Min</code>, <code>Max</code>, <code>Average</code> can be used with groupings.</p>
</div>
</div>
<div class="sect2">
<h3 id="ordering">Ordering</h3>
<div class="paragraph">
<p><code>OrderBy</code>, <code>OrderByDescending</code>, <code>ThenBy</code>, <code>ThenByDescending</code> are supported. You can combine them to order by multiple columns:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="csharp"><span class="kt">var</span> <span class="n">booksOrderedByAuthorAndYear</span> <span class="p">=</span> <span class="n">bookTable</span><span class="p">.</span><span class="n">GetRecordView</span><span class="p">&lt;</span><span class="n">Book</span><span class="p">&gt;().</span><span class="nf">AsQueryable</span><span class="p">()</span>
<span class="p">.</span><span class="nf">OrderBy</span><span class="p">(</span><span class="n">book</span> <span class="p">=&gt;</span> <span class="n">book</span><span class="p">.</span><span class="n">Author</span><span class="p">)</span>
<span class="p">.</span><span class="nf">ThenByDescending</span><span class="p">(</span><span class="n">book</span> <span class="p">=&gt;</span> <span class="n">book</span><span class="p">.</span><span class="n">Year</span><span class="p">)</span>
<span class="p">.</span><span class="nf">ToList</span><span class="p">();</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="union-intersect-except">Union, Intersect, Except</h3>
<div class="paragraph">
<p>Multiple result sets can be combined by using the <code>Union</code>, <code>Intersect</code>, <code>Except</code> methods. For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="csharp"><span class="n">IQueryable</span><span class="p">&lt;</span><span class="kt">string</span><span class="p">&gt;</span> <span class="n">employeeEmails</span> <span class="p">=</span> <span class="n">employeeTable</span>
<span class="p">.</span><span class="n">GetRecordView</span><span class="p">&lt;</span><span class="n">Employee</span><span class="p">&gt;().</span><span class="nf">AsQueryable</span><span class="p">()</span>
<span class="p">.</span><span class="nf">Select</span><span class="p">(</span><span class="n">x</span> <span class="p">=&gt;</span> <span class="n">x</span><span class="p">.</span><span class="n">Email</span><span class="p">);</span>
<span class="n">IQueryable</span><span class="p">&lt;</span><span class="kt">string</span><span class="p">&gt;</span> <span class="n">customerEmails</span> <span class="p">=</span> <span class="n">customerTable</span>
<span class="p">.</span><span class="n">GetRecordView</span><span class="p">&lt;</span><span class="n">Customer</span><span class="p">&gt;().</span><span class="nf">AsQueryable</span><span class="p">()</span>
<span class="p">.</span><span class="nf">Select</span><span class="p">(</span><span class="n">x</span> <span class="p">=&gt;</span> <span class="n">x</span><span class="p">.</span><span class="n">Email</span><span class="p">);</span>
<span class="n">List</span><span class="p">&lt;</span><span class="kt">string</span><span class="p">&gt;</span> <span class="n">allEmails</span> <span class="p">=</span> <span class="n">employeeEmails</span><span class="p">.</span><span class="nf">Union</span><span class="p">(</span><span class="n">customerEmails</span><span class="p">)</span>
<span class="p">.</span><span class="nf">OrderBy</span><span class="p">(</span><span class="n">x</span> <span class="p">=&gt;</span> <span class="n">x</span><span class="p">)</span>
<span class="p">.</span><span class="nf">ToList</span><span class="p">();</span>
<span class="n">List</span><span class="p">&lt;</span><span class="kt">string</span><span class="p">&gt;</span> <span class="n">employeesThatAreCustomers</span> <span class="p">=</span> <span class="n">employeeEmails</span>
<span class="p">.</span><span class="nf">Intersect</span><span class="p">(</span><span class="n">customerEmails</span><span class="p">).</span><span class="nf">ToList</span><span class="p">();</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="aggregate-functions">Aggregate Functions</h3>
<div class="paragraph">
<p>Below is a list of .NET aggregate functions and their SQL equivalents that are supported in Apache Ignite:</p>
</div>
<table class="tableblock frame-all grid-all stripes-even" style="width: 70%;">
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 33.3333%;">
<col style="width: 33.3334%;">
</colgroup>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">LINQ synchronous method</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">LINQ asynchronous method</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">SQL Operator</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">First</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">FirstAsync</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">FIRST</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">FirstOrDefault</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">FirstOrDefaultAsync</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">FIRST &#8230;&#8203; LIMIT 1</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Single</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">SingleAsync</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">FIRST</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">SingleOrDefault</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">SingleOrDefaultAsync</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">FIRST &#8230;&#8203; LIMIT 2</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Max</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">MaxAsync</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">MAX</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Min</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">MinAsync</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">MIN</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Average</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">AverageAsync</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">AVG</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Sum</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">SumAsync</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">SUM</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Count</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">CountAsync</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">COUNT</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">LongCount</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">LongCountAsync</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">COUNT</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Any</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">AnyAsync</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">ANY</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">All</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">AllAsync</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">ALL</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>Here are examples of how you can use these methods:</p>
</div>
<code-tabs><code-tab data-tab='Synchronous'><div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="csharp"><span class="n">Person</span> <span class="n">first</span> <span class="p">=</span> <span class="n">query</span><span class="p">.</span><span class="nf">First</span><span class="p">();</span>
<span class="n">Person</span><span class="p">?</span> <span class="n">firstOrDefault</span> <span class="p">=</span> <span class="n">query</span><span class="p">.</span><span class="nf">FirstOrDefault</span><span class="p">();</span>
<span class="n">Person</span> <span class="n">single</span> <span class="p">=</span> <span class="n">query</span><span class="p">.</span><span class="nf">Single</span><span class="p">();</span>
<span class="n">Person</span><span class="p">?</span> <span class="n">singleOrDefault</span> <span class="p">=</span> <span class="n">query</span><span class="p">.</span><span class="nf">SingleOrDefault</span><span class="p">();</span>
<span class="kt">int</span> <span class="n">maxAge</span> <span class="p">=</span> <span class="n">query</span><span class="p">.</span><span class="nf">Max</span><span class="p">(</span><span class="n">x</span> <span class="p">=&gt;</span> <span class="n">x</span><span class="p">.</span><span class="n">Age</span><span class="p">);</span>
<span class="kt">int</span> <span class="n">minAge</span> <span class="p">=</span> <span class="n">query</span><span class="p">.</span><span class="nf">Min</span><span class="p">(</span><span class="n">x</span> <span class="p">=&gt;</span> <span class="n">x</span><span class="p">.</span><span class="n">Age</span><span class="p">);</span>
<span class="kt">int</span> <span class="n">avgAge</span> <span class="p">=</span> <span class="n">query</span><span class="p">.</span><span class="nf">Average</span><span class="p">(</span><span class="n">x</span> <span class="p">=&gt;</span> <span class="n">x</span><span class="p">.</span><span class="n">Age</span><span class="p">);</span>
<span class="kt">int</span> <span class="n">sumAge</span> <span class="p">=</span> <span class="n">query</span><span class="p">.</span><span class="nf">Sum</span><span class="p">(</span><span class="n">x</span> <span class="p">=&gt;</span> <span class="n">x</span><span class="p">.</span><span class="n">Age</span><span class="p">);</span>
<span class="kt">int</span> <span class="n">count</span> <span class="p">=</span> <span class="n">query</span><span class="p">.</span><span class="nf">Count</span><span class="p">();</span>
<span class="kt">long</span> <span class="n">longCount</span> <span class="p">=</span> <span class="n">query</span><span class="p">.</span><span class="nf">LongCount</span><span class="p">();</span>
<span class="kt">bool</span> <span class="n">any</span> <span class="p">=</span> <span class="n">query</span><span class="p">.</span><span class="nf">Any</span><span class="p">(</span><span class="n">x</span> <span class="p">=&gt;</span> <span class="n">x</span><span class="p">.</span><span class="n">Age</span> <span class="p">&gt;</span> <span class="m">30</span><span class="p">);</span>
<span class="kt">bool</span> <span class="n">all</span> <span class="p">=</span> <span class="n">query</span><span class="p">.</span><span class="nf">All</span><span class="p">(</span><span class="n">x</span> <span class="p">=&gt;</span> <span class="n">x</span><span class="p">.</span><span class="n">Age</span> <span class="p">&gt;</span> <span class="m">30</span><span class="p">);</span></code></pre>
</div>
</div></code-tab><code-tab data-tab='Asynchronous'><div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="csharp"><span class="n">Person</span> <span class="n">first</span> <span class="p">=</span> <span class="k">await</span> <span class="n">query</span><span class="p">.</span><span class="nf">FirstAsync</span><span class="p">();</span>
<span class="n">Person</span><span class="p">?</span> <span class="n">firstOrDefault</span> <span class="p">=</span> <span class="k">await</span> <span class="n">query</span><span class="p">.</span><span class="nf">FirstOrDefaultAsync</span><span class="p">();</span>
<span class="n">Person</span> <span class="n">single</span> <span class="p">=</span> <span class="k">await</span> <span class="n">query</span><span class="p">.</span><span class="nf">SingleAsync</span><span class="p">();</span>
<span class="n">Person</span><span class="p">?</span> <span class="n">singleOrDefault</span> <span class="p">=</span> <span class="k">await</span> <span class="n">query</span><span class="p">.</span><span class="nf">SingleOrDefaultAsync</span><span class="p">();</span>
<span class="kt">int</span> <span class="n">maxAge</span> <span class="p">=</span> <span class="k">await</span> <span class="n">query</span><span class="p">.</span><span class="nf">MaxAsync</span><span class="p">(</span><span class="n">x</span> <span class="p">=&gt;</span> <span class="n">x</span><span class="p">.</span><span class="n">Age</span><span class="p">);</span>
<span class="kt">int</span> <span class="n">minAge</span> <span class="p">=</span> <span class="k">await</span> <span class="n">query</span><span class="p">.</span><span class="nf">MinAsync</span><span class="p">(</span><span class="n">x</span> <span class="p">=&gt;</span> <span class="n">x</span><span class="p">.</span><span class="n">Age</span><span class="p">);</span>
<span class="kt">int</span> <span class="n">avgAge</span> <span class="p">=</span> <span class="k">await</span> <span class="n">query</span><span class="p">.</span><span class="nf">AverageAsync</span><span class="p">(</span><span class="n">x</span> <span class="p">=&gt;</span> <span class="n">x</span><span class="p">.</span><span class="n">Age</span><span class="p">);</span>
<span class="kt">int</span> <span class="n">sumAge</span> <span class="p">=</span> <span class="k">await</span> <span class="n">query</span><span class="p">.</span><span class="nf">SumAsync</span><span class="p">(</span><span class="n">x</span> <span class="p">=&gt;</span> <span class="n">x</span><span class="p">.</span><span class="n">Age</span><span class="p">);</span>
<span class="kt">int</span> <span class="n">count</span> <span class="p">=</span> <span class="k">await</span> <span class="n">query</span><span class="p">.</span><span class="nf">CountAsync</span><span class="p">();</span>
<span class="kt">long</span> <span class="n">longCount</span> <span class="p">=</span> <span class="k">await</span> <span class="n">query</span><span class="p">.</span><span class="nf">LongCountAsync</span><span class="p">();</span>
<span class="kt">bool</span> <span class="n">any</span> <span class="p">=</span> <span class="k">await</span> <span class="n">query</span><span class="p">.</span><span class="nf">AnyAsync</span><span class="p">(</span><span class="n">x</span> <span class="p">=&gt;</span> <span class="n">x</span><span class="p">.</span><span class="n">Age</span> <span class="p">&gt;</span> <span class="m">30</span><span class="p">);</span>
<span class="kt">bool</span> <span class="n">all</span> <span class="p">=</span> <span class="k">await</span> <span class="n">query</span><span class="p">.</span><span class="nf">AllAsync</span><span class="p">(</span><span class="n">x</span> <span class="p">=&gt;</span> <span class="n">x</span><span class="p">.</span><span class="n">Age</span> <span class="p">&gt;</span> <span class="m">30</span><span class="p">);</span></code></pre>
</div>
</div></code-tab></code-tabs>
</div>
<div class="sect2">
<h3 id="math-functions">Math Functions</h3>
<div class="paragraph">
<p>The following <code>Math</code> functions are supported (will be translated to SQL equivalents):
<code>Abs</code>, <code>Cos</code>, <code>Cosh</code>, <code>Acos</code>, <code>Sin</code>, <code>Sinh</code>, <code>Asin</code>, <code>Tan</code>, <code>Tanh</code>, <code>Atan</code>, <code>Ceiling</code>, <code>Floor</code>,
<code>Exp</code>, <code>Log</code>, <code>Log10</code>, <code>Pow</code>, <code>Round</code>, <code>Sign</code>, <code>Sqrt</code>, <code>Truncate</code>.</p>
</div>
<div class="paragraph">
<p>The following <code>Math</code> functions are NOT supported (no equivalent in Ignite SQL engine):
<code>Acosh</code>, <code>Asinh</code>, <code>Atanh</code>, <code>Atan2</code>, <code>Log2</code>, <code>Log(x, y)</code>.</p>
</div>
<div class="paragraph">
<p>Here is the example of how you can use math functions:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="csharp"><span class="kt">var</span> <span class="n">triangles</span> <span class="p">=</span> <span class="n">table</span><span class="p">.</span><span class="n">GetRecordView</span><span class="p">&lt;</span><span class="n">Triangle</span><span class="p">&gt;().</span><span class="nf">AsQueryable</span><span class="p">()</span>
<span class="p">.</span><span class="nf">Select</span><span class="p">(</span><span class="n">t</span> <span class="p">=&gt;</span> <span class="k">new</span> <span class="p">{</span>
<span class="n">Hypotenuse</span><span class="p">,</span>
<span class="n">Opposite</span> <span class="p">=</span> <span class="n">t</span><span class="p">.</span><span class="n">Hypotenuse</span> <span class="p">*</span> <span class="n">Math</span><span class="p">.</span><span class="nf">Sin</span><span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">Angle</span><span class="p">),</span>
<span class="n">Adjacent</span> <span class="p">=</span> <span class="n">t</span><span class="p">.</span><span class="n">Hypotenuse</span> <span class="p">*</span> <span class="n">Math</span><span class="p">.</span><span class="nf">Cos</span><span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">Angle</span><span class="p">)</span>
<span class="p">})</span>
<span class="p">.</span><span class="nf">ToList</span><span class="p">();</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="string-functions">String Functions</h3>
<div class="paragraph">
<p>The following string functions are supported: <code>string.Compare(string)</code>, <code>string.Compare(string, bool ignoreCase)</code>, concatenation <code>s1 + s2 + s3</code>, <code>ToUpper</code>, <code>ToLower</code>,
<code>Substring(start)</code>, <code>Substring(start, len)</code>,
<code>Trim</code>, <code>Trim(char)</code>, <code>TrimStart</code>, <code>TrimStart(char)</code>, <code>TrimEnd</code>, <code>TrimEnd(char)</code>,
<code>Contains</code>, <code>StartsWith</code>, <code>EndsWith</code>, <code>IndexOf</code>, <code>Length</code>, <code>Replace</code>.</p>
</div>
<div class="paragraph">
<p>Here is the example of how you can use string functions:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="csharp"><span class="n">List</span><span class="p">&lt;</span><span class="kt">string</span><span class="p">&gt;</span> <span class="n">fullNames</span> <span class="p">=</span> <span class="n">table</span><span class="p">.</span><span class="n">GetRecordView</span><span class="p">&lt;</span><span class="n">Person</span><span class="p">&gt;().</span><span class="nf">AsQueryable</span><span class="p">()</span>
<span class="p">.</span><span class="nf">Where</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">FirstName</span><span class="p">.</span><span class="nf">StartsWith</span><span class="p">(</span><span class="s">"Jo"</span><span class="p">))</span>
<span class="p">.</span><span class="nf">Select</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="k">new</span> <span class="p">{</span>
<span class="n">FullName</span> <span class="p">=</span> <span class="n">p</span><span class="p">.</span><span class="n">FirstName</span><span class="p">.</span><span class="nf">ToUpper</span><span class="p">()</span> <span class="p">+</span>
<span class="s">" "</span> <span class="p">+</span>
<span class="n">p</span><span class="p">.</span><span class="n">LastName</span><span class="p">.</span><span class="nf">ToLower</span><span class="p">()</span> <span class="p">})</span>
<span class="p">.</span><span class="nf">ToList</span><span class="p">();</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="regular-expressions">Regular Expressions</h3>
<div class="paragraph">
<p><code>Regex.Replace</code> is translated to <code>regexp_replace</code> function. Here is how you can use regular expressions in your code:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="csharp"><span class="n">List</span><span class="p">&lt;</span><span class="kt">string</span><span class="p">&gt;</span> <span class="n">addresses</span> <span class="p">=</span> <span class="n">table</span><span class="p">.</span><span class="n">GetRecordView</span><span class="p">&lt;</span><span class="n">Person</span><span class="p">&gt;().</span><span class="nf">AsQueryable</span><span class="p">()</span>
<span class="p">.</span><span class="nf">Select</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="k">new</span> <span class="p">{</span> <span class="n">Address</span> <span class="p">=</span> <span class="n">Regex</span><span class="p">.</span><span class="nf">Replace</span><span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">Address</span><span class="p">,</span> <span class="s">@"(\d+)"</span><span class="p">,</span> <span class="s">"[$1]"</span><span class="p">)</span>
<span class="p">.</span><span class="nf">ToList</span><span class="p">();</span></code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
Regular expression engine within SQL may behave differently from .NET engine.
</td>
</tr>
</table>
</div>
</div>
<div class="sect2">
<h3 id="dml-bulk-update-and-delete">DML (Bulk Update and Delete)</h3>
<div class="paragraph">
<p>Bulk update and delete with optional conditions are supported through <code>ExecuteUpdateAsync</code> and <code>ExecuteDeleteAsync</code> extensions methods on <code>IQueryable&lt;T&gt;</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="csharp"><span class="kt">var</span> <span class="n">orders</span> <span class="p">=</span> <span class="n">orderTable</span><span class="p">.</span><span class="n">GetRecordView</span><span class="p">&lt;</span><span class="n">Order</span><span class="p">&gt;().</span><span class="nf">AsQueryable</span><span class="p">();</span>
<span class="k">await</span> <span class="n">orders</span><span class="p">.</span><span class="nf">Where</span><span class="p">(</span><span class="n">x</span> <span class="p">=&gt;</span> <span class="n">x</span><span class="p">.</span><span class="n">Amount</span> <span class="p">==</span> <span class="m">0</span><span class="p">).</span><span class="nf">ExecuteDeleteAsync</span><span class="p">();</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Update statement can set properties to constant values or to an expression based on other properties of the same row:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="csharp"><span class="kt">var</span> <span class="n">orders</span> <span class="p">=</span> <span class="n">orderTable</span><span class="p">.</span><span class="n">GetRecordView</span><span class="p">&lt;</span><span class="n">Order</span><span class="p">&gt;().</span><span class="nf">AsQueryable</span><span class="p">();</span>
<span class="k">await</span> <span class="n">orders</span>
<span class="p">.</span><span class="nf">Where</span><span class="p">(</span><span class="n">x</span> <span class="p">=&gt;</span> <span class="n">x</span><span class="p">.</span><span class="n">CustomerId</span> <span class="p">==</span> <span class="n">customerId</span><span class="p">)</span>
<span class="p">.</span><span class="nf">ExecuteUpdateAsync</span><span class="p">(</span>
<span class="n">order</span> <span class="p">=&gt;</span> <span class="n">order</span><span class="p">.</span><span class="nf">SetProperty</span><span class="p">(</span><span class="n">x</span> <span class="p">=&gt;</span> <span class="n">x</span><span class="p">.</span><span class="n">Discount</span><span class="p">,</span> <span class="m">0.1m</span><span class="p">)</span>
<span class="p">.</span><span class="nf">SetProperty</span><span class="p">(</span><span class="n">x</span> <span class="p">=&gt;</span> <span class="n">x</span><span class="p">.</span><span class="n">Note</span><span class="p">,</span> <span class="n">x</span> <span class="p">=&gt;</span> <span class="n">x</span><span class="p">.</span><span class="n">Note</span> <span class="p">+</span>
<span class="s">" Happy birthday, "</span> <span class="p">+</span>
<span class="n">x</span><span class="p">.</span><span class="n">CustomerName</span><span class="p">));</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Resulting SQL:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="csharp"><span class="n">update</span> <span class="n">PUBLIC</span><span class="p">.</span><span class="n">tbl1</span> <span class="k">as</span> <span class="n">_T0</span>
<span class="k">set</span> <span class="n">NOTE</span> <span class="p">=</span> <span class="nf">concat</span><span class="p">(</span><span class="nf">concat</span><span class="p">(</span><span class="n">_T0</span><span class="p">.</span><span class="n">NOTE</span><span class="p">,</span> <span class="p">?),</span> <span class="n">_T0</span><span class="p">.</span><span class="n">CUSTOMERNAME</span><span class="p">),</span> <span class="n">DISCOUNT</span> <span class="p">=</span> <span class="p">?</span>
<span class="k">where</span> <span class="p">(</span><span class="n">_T0</span><span class="p">.</span><span class="n">CUSTOMERID</span> <span class="n">IS</span> <span class="n">NOT</span> <span class="n">DISTINCT</span> <span class="n">FROM</span> <span class="p">?)</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="composing-queries">Composing Queries</h3>
<div class="paragraph">
<p><code>IQueryable&lt;T&gt;</code> expressions can be composed dynamically. A common use case is to compose a query based on user input.
For example, optional filters on different columns can be applied to a query:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="csharp"><span class="k">public</span> <span class="n">List</span><span class="p">&lt;</span><span class="n">Book</span><span class="p">&gt;</span> <span class="nf">GetBooks</span><span class="p">(</span><span class="kt">string</span><span class="p">?</span> <span class="n">author</span><span class="p">,</span> <span class="kt">int</span><span class="p">?</span> <span class="n">year</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">IQueryable</span><span class="p">&lt;</span><span class="n">Book</span><span class="p">&gt;</span> <span class="n">query</span> <span class="p">=</span> <span class="n">bookTable</span><span class="p">.</span><span class="n">GetRecordView</span><span class="p">&lt;</span><span class="n">Book</span><span class="p">&gt;().</span><span class="nf">AsQueryable</span><span class="p">();</span>
<span class="k">if</span> <span class="p">(!</span><span class="kt">string</span><span class="p">.</span><span class="nf">IsNullOrEmpty</span><span class="p">(</span><span class="n">author</span><span class="p">))</span>
<span class="n">query</span> <span class="p">=</span> <span class="n">query</span><span class="p">.</span><span class="nf">Where</span><span class="p">(</span><span class="n">x</span> <span class="p">=&gt;</span> <span class="n">x</span><span class="p">.</span><span class="n">Author</span> <span class="p">==</span> <span class="n">author</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">year</span> <span class="p">!=</span> <span class="k">null</span><span class="p">)</span>
<span class="n">query</span> <span class="p">=</span> <span class="n">query</span><span class="p">.</span><span class="nf">Where</span><span class="p">(</span><span class="n">x</span> <span class="p">=&gt;</span> <span class="n">x</span><span class="p">.</span><span class="n">Year</span> <span class="p">==</span> <span class="n">year</span><span class="p">);</span>
<span class="k">return</span> <span class="n">query</span><span class="p">.</span><span class="nf">ToList</span><span class="p">();</span>
<span class="p">}</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="column-name-mapping">Column Name Mapping</h3>
<div class="paragraph">
<p>Unless custom mapping is provided with <code>[Column]</code>, LINQ provider will use property or field names as column names,
using unquoted identifiers, which are case-insensitive.</p>
</div>
<code-tabs><code-tab data-tab='C#'><div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="csharp"><span class="n">bookTable</span><span class="p">.</span><span class="n">GetRecordView</span><span class="p">&lt;</span><span class="n">Book</span><span class="p">&gt;().</span><span class="nf">AsQueryable</span><span class="p">().</span><span class="nf">Select</span><span class="p">(</span><span class="n">x</span> <span class="p">=&gt;</span> <span class="n">x</span><span class="p">.</span><span class="n">Author</span><span class="p">).</span><span class="nf">ToList</span><span class="p">();</span></code></pre>
</div>
</div></code-tab><code-tab data-tab='Resulting SQL'><div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="csharp"><span class="k">select</span> <span class="n">_T0</span><span class="p">.</span><span class="n">AUTHOR</span> <span class="k">from</span> <span class="n">PUBLIC</span><span class="p">.</span><span class="n">books</span> <span class="k">as</span> <span class="n">_T0</span></code></pre>
</div>
</div></code-tab></code-tabs>
<div class="paragraph">
<p>To use quoted identifiers, or to map column names to different property names, use <code>[Column]</code> attribute:</p>
</div>
<code-tabs><code-tab data-tab='C#'><div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="csharp"><span class="k">public</span> <span class="k">class</span> <span class="nc">Book</span>
<span class="p">{</span>
<span class="p">[</span><span class="nf">Column</span><span class="p">(</span><span class="s">"book_author"</span><span class="p">)]</span>
<span class="k">public</span> <span class="kt">string</span> <span class="n">Author</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="p">}</span>
<span class="c1">// Or a record:</span>
<span class="k">public</span> <span class="k">record</span> <span class="nc">Book</span><span class="p">([</span><span class="n">property</span><span class="p">:</span> <span class="nf">Column</span><span class="p">(</span><span class="s">"book_author"</span><span class="p">)]</span> <span class="kt">string</span> <span class="n">Author</span><span class="p">);</span></code></pre>
</div>
</div></code-tab><code-tab data-tab='Resulting SQL'><div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="sql"><span class="k">SELECT</span> <span class="n">_T0</span><span class="p">.</span><span class="nv">"book_author"</span> <span class="k">FROM</span> <span class="k">PUBLIC</span><span class="p">.</span><span class="n">books</span> <span class="k">AS</span> <span class="n">_T0</span></code></pre>
</div>
</div></code-tab></code-tabs>
</div>
<div class="sect2">
<h3 id="keyvalueview">KeyValueView</h3>
<div class="paragraph">
<p>All examples above use <code>IRecordView&lt;T&gt;</code> to perform queries; LINQ provider supports <code>IKeyValueView&lt;TK, TV&gt;</code> equally well:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="csharp"><span class="n">IQueryable</span><span class="p">&lt;</span><span class="n">KeyValuePair</span><span class="p">&lt;</span><span class="kt">int</span><span class="p">,</span> <span class="n">Book</span><span class="p">&gt;&gt;</span> <span class="n">query</span> <span class="p">=</span>
<span class="n">bookTable</span><span class="p">.</span><span class="n">GetKeyValueView</span><span class="p">&lt;</span><span class="kt">int</span><span class="p">,</span> <span class="n">Book</span><span class="p">&gt;().</span><span class="nf">AsQueryable</span><span class="p">();</span>
<span class="n">List</span><span class="p">&lt;</span><span class="n">Book</span><span class="p">&gt;</span> <span class="n">books</span> <span class="p">=</span> <span class="n">query</span>
<span class="p">.</span><span class="nf">Where</span><span class="p">(</span><span class="n">x</span> <span class="p">=&gt;</span> <span class="n">x</span><span class="p">.</span><span class="n">Key</span> <span class="p">&gt;</span> <span class="m">10</span><span class="p">)</span>
<span class="p">.</span><span class="nf">Select</span><span class="p">(</span><span class="n">x</span> <span class="p">=&gt;</span> <span class="n">x</span><span class="p">.</span><span class="n">Value</span><span class="p">)</span>
<span class="p">.</span><span class="nf">ToList</span><span class="p">();</span></code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="copyright">
© 2024 The Apache Software Foundation.<br/>
Apache, Apache Ignite, the Apache feather and the Apache Ignite logo are either registered trademarks or trademarks of The Apache Software Foundation.
</div>
</article>
<nav class="right-nav" data-swiftype-index='false'>
<div class="toc-wrapper">
<ul class="sectlevel1">
<li><a href="#getting-started-with-linq">Getting Started With LINQ</a></li>
<li><a href="#using-linq">Using LINQ</a>
<ul class="sectlevel2">
<li><a href="#inspecting-generated-sql">Inspecting Generated SQL</a></li>
<li><a href="#transactions">Transactions</a></li>
<li><a href="#custom-query-options">Custom Query Options</a></li>
<li><a href="#result-materialization">Result Materialization</a>
<ul class="sectlevel3">
<li><a href="#iteration">Iteration</a></li>
<li><a href="#converting-to-collections">Converting to Collections</a></li>
<li><a href="#ignite-specific-iresultset">Ignite-specific IResultSet</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#supported-linq-features">Supported LINQ Features</a>
<ul class="sectlevel2">
<li><a href="#projection">Projection</a></li>
<li><a href="#inner-joins">Inner Joins</a></li>
<li><a href="#outer-joins">Outer Joins</a></li>
<li><a href="#grouping">Grouping</a></li>
<li><a href="#ordering">Ordering</a></li>
<li><a href="#union-intersect-except">Union, Intersect, Except</a></li>
<li><a href="#aggregate-functions">Aggregate Functions</a></li>
<li><a href="#math-functions">Math Functions</a></li>
<li><a href="#string-functions">String Functions</a></li>
<li><a href="#regular-expressions">Regular Expressions</a></li>
<li><a href="#dml-bulk-update-and-delete">DML (Bulk Update and Delete)</a></li>
<li><a href="#composing-queries">Composing Queries</a></li>
<li><a href="#column-name-mapping">Column Name Mapping</a></li>
<li><a href="#keyvalueview">KeyValueView</a></li>
</ul>
</li>
</ul>
</div>
<nav class="promo-nav">
<!--#include virtual="/includes/docs_rightnav_promotion.html" -->
<a href="#" data-trigger-bugyard-feedback="true" id="doc-feedback-btn">Docs Feedback</a>
</nav>
</nav>
</section>
<script type='module' src='/assets/js/code-copy-to-clipboard.js' async crossorigin></script>
<script>
// inits deep anchors -- needs to be done here because of https://www.bryanbraun.com/anchorjs/#dont-run-it-too-late
anchors.add('.page-docs h1, .page-docs h2, .page-docs h3:not(.discrete), .page-docs h4, .page-docs h5');
anchors.options = {
placement: 'right',
visible: 'always'
};
</script>
<script src="https://cdn.jsdelivr.net/npm/docsearch.js@2/dist/cdn/docsearch.min.js"></script>
<script>
docsearch({
// Your apiKey and indexName will be given to you once
// we create your config
apiKey: '9ee37627b9bdf4b39d6b3aa20452a779',
appId: 'DAYEVYFD60',
indexName: 'apache_ignite',
// Replace inputSelector with a CSS selector
// matching your search input
inputSelector: '#search-input',
// algoliaOptions: { 'facetFilters': ["version:$VERSION"] },
// Set debug to true to inspect the dropdown
debug: false,
});
</script>
<script type='module' src='/assets/js/index.js?1708608103' async crossorigin></script>
<script type='module' src='/assets/js/versioning.js?1708608103' async crossorigin></script>
<script type='module' src='/assets/js/railroad-diagram.js?1708608103' async></script>
<link rel="stylesheet" href="/assets/css/styles.css?1708608103" media="print" onload="this.media='all'">
<noscript><link media="all" rel="stylesheet" href="/assets/css/styles.css?1708608103"></noscript>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/docsearch.js@2/dist/cdn/docsearch.min.css" media="print" onload="this.media='all'">
<noscript><link media="all" rel="stylesheet" href="https://cdn.jsdelivr.net/npm/docsearch.js@2/dist/cdn/docsearch.min.css"></noscript>
</body>
</html>