{"id":29675925,"url":"https://github.com/jessebenson/service-fabric-queryable","last_synced_at":"2026-03-11T05:31:46.289Z","repository":{"id":85200036,"uuid":"91866214","full_name":"jessebenson/service-fabric-queryable","owner":"jessebenson","description":"Enable query support for your stateful services in Service Fabric via the OData protocol.","archived":false,"fork":false,"pushed_at":"2019-05-06T19:34:06.000Z","size":351,"stargazers_count":43,"open_issues_count":5,"forks_count":9,"subscribers_count":10,"default_branch":"master","last_synced_at":"2025-09-27T03:45:07.138Z","etag":null,"topics":["microservices","microsoft","odata","query","queryable","reliable-collections","reliable-stateful-service","servicefabric"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jessebenson.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-05-20T04:57:36.000Z","updated_at":"2025-06-20T15:05:35.000Z","dependencies_parsed_at":"2023-02-26T12:15:14.875Z","dependency_job_id":null,"html_url":"https://github.com/jessebenson/service-fabric-queryable","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/jessebenson/service-fabric-queryable","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jessebenson%2Fservice-fabric-queryable","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jessebenson%2Fservice-fabric-queryable/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jessebenson%2Fservice-fabric-queryable/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jessebenson%2Fservice-fabric-queryable/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jessebenson","download_url":"https://codeload.github.com/jessebenson/service-fabric-queryable/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jessebenson%2Fservice-fabric-queryable/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30372170,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-10T21:41:54.280Z","status":"online","status_checked_at":"2026-03-11T02:00:07.027Z","response_time":84,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["microservices","microsoft","odata","query","queryable","reliable-collections","reliable-stateful-service","servicefabric"],"created_at":"2025-07-22T23:39:04.905Z","updated_at":"2026-03-11T05:31:46.252Z","avatar_url":"https://github.com/jessebenson.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ServiceFabric.Extensions.Services.Queryable\n\n## Getting Started\n\n1. Create a stateful ASP.NET Core service.\n\n2. Add the **ServiceFabric.Extensions.Services.Queryable** nuget package.\n\n3. Add the **ODataQueryable** middleware to your Startup.cs.  This will intercept calls to the /$query endpoint to expose OData query capabilities over the reliable collections in your service.\n\n```csharp\nusing ServiceFabric.Extensions.Services.Queryable;\n\npublic class Startup\n{\n\tpublic void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)\n\t{\n\t\t...\n\t\tapp.UseODataQueryable();\n\t\t...\n\t}\n}\n```\nAdd the ODataQueryable middleware to your stateful services (using ASP.NET Core stateful services), ensure Reverse Proxy is enabled, and start querying your reliable collections.  \n\n## Use `rcctl` to query your middleware\n[There is a command line tool you can use to query your middleware endpoints called `rcctl`.](https://github.com/shalabhms/reliable-collections-cli)\n\nYou can install it and start using it with\n\n```shell\npip install rcctl\n```\n\n## Use REST calls to query your middleware\n\nYou can interact directly with the middleware by constructing REST calls. If your service is named 'fabric:/MyApp/MyService' and your reliable dictionary is named 'my-dictionary', try queries like:\n\nGet OData metadata about a single partition stateful service:\n- ```GET http://localhost:19081/MyApp/MyService/$query/$metadata```\n\nGet OData metadata about a partitioned stateful service:\n- ```GET http://localhost:19081/MyApp/MyService/$query/$metadata?PartitionKind=Int64Range\u0026PartitionKey=0```\n\nGet 10 items from the reliable dictionary.\n- ```GET http://localhost:19081/MyApp/MyService/$query/my-dictionary?$top=10```\n\nGet 10 items with Quantity between 2 and 4, inclusively.\n- ```GET http://localhost:19081/MyApp/MyService/$query/my-dictionary?$top=10\u0026$filter=Quantity ge 2 and Quantity le 4```\n\nGet 10 items, returning only the Price and Quantity properties, sorted by Price in descending order.\n- ```GET http://localhost:19081/MyApp/MyService/$query/my-dictionary?$top=10\u0026$select=Price,Quantity\u0026$orderby=Price desc```\n\n## Use ReliableIndexedDictionaries to speed up your queries by taking advantage of secondary indices\nSome queries may take a long time or not complete. If you expect that you will be querying against a field often, you should consider adding a secondary index on that field, which will dramatically speed up your queries.\n\nTo do so, when you are making your dictionary, instead of using \n\n```StateManager.GetOrAddAsync\u003cIReliableDictionary\u003e(\"name\")```\n\nyou should use \n\n```\nStateManager.GetOrAddIndexedAsync(\"name\",\n\tFilterableIndex\u003cKeyType, ValueType, Property1Type\u003e.CreateQueryableInstance(\"Property1Name\"),\n\tFilterableIndex\u003cKeyType, ValueType, Property2Type\u003e.CreateQueryableInstance(\"Property2Name\"),\n\tetc.)\n```\n\nThis will create a dictionary with secondary indices on `ValueType.Property1Name` and `ValueType.Property2Name`. To find out more about ReliableIndexedDictionary go to the [indexing repository](https://github.com/jessebenson/service-fabric-indexing)\n\nNote: you have to create your indexes the first time you define your dictionary. If you make them later, they will not be truly consistent with the dictionary and this can lead to failed requests or data corruption.\n\nNow, if we made a secondary index on a property called `Age` on our `ValueType`, these queries would be faster because of indexing:\n- ```$filter=Value.Age eq 20```\n- ```$filter=Value.Age gt 25```\n- ```$filter=Value.Age le 40 and Value.Name eq \"John\"```\n\nHowever the following would not be faster than without using an indexed dictionary:\n- ```$filter=Value.Name eq \"John\"```\n- ```$filter=Value.Age le 40 or Value.Name eq \"John\"```\n\nIf we added a secondary index on both `Age` and `Name`, then all the above queries would be faster.\n\nCheck out [`UserSvc`](samples/Basic/Basic.UserSvc/UserSvc.cs) in the  [BasicApp sample](samples/Basic) to see both an unindexed and an indexed dictionary being constructed.\n\n## Using LINQ to query ReliableIndexedDictionaries\nIn addition to external requests through the OData middleware, ReliableIndexedDictionaries can be queried from your application code using LINQ. However, similarly to external queries, not all queries will work effectively with indexing. If your query is not supported, you should use `GetAllAsync()` to get the entire result set and apply your LINQ query against that.\n\nTo create a queryable instance of your IReliableIndexedDictionary, call:\n```csharp\nvar qd = new QueryableReliableIndexedDictionary\u003cTKey, TValue, TValue\u003e(indexedDictionary, stateManager);\n```\nThen you can carry out queries such as:\n```csharp\n\nvar query = qd.Where(x =\u003e x.Age == 25);\nvar query = qd.Where(x =\u003e x.Age \u003e= 25).Select(x =\u003e x.Email);\nvar query = from Person person in qd\n            where person.Age \u003e= 25 \u0026\u0026 person.Email == \"user-0@example.com\"\n            select person.Email;\nvar query = qd.Where(x =\u003e x.Name.CompareTo(\"Name1\") \u003e= 0);\n```\nSome import notes for querying:\n1. Put all your WHERE logic in a single `Where` statement and join using `\u0026\u0026` and `||` operators, as the query may not be efficient if it is spread across multiple WHERE clauses.\n2. If you want to compare an IComparable type that does not have \"\u003e\", \"\u003c=\" operators, you must give it in the form: `property.CompareTo(constant) '\u003e,\u003c,\u003c=,=\u003e' 0` \n\n## Samples\n\n- [Basic application with several stateful services](samples/Basic)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjessebenson%2Fservice-fabric-queryable","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjessebenson%2Fservice-fabric-queryable","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjessebenson%2Fservice-fabric-queryable/lists"}