{"id":13601192,"url":"https://github.com/axelheer/nein-linq","last_synced_at":"2025-04-11T01:31:08.896Z","repository":{"id":24585932,"uuid":"27994019","full_name":"axelheer/nein-linq","owner":"axelheer","description":"NeinLinq provides helpful extensions for using LINQ providers such as Entity Framework that support only a minor subset of .NET functions, reusing functions, rewriting queries, even making them null-safe, and building dynamic queries using translatable predicates and selectors.","archived":false,"fork":false,"pushed_at":"2025-03-08T18:17:29.000Z","size":1844,"stargazers_count":534,"open_issues_count":2,"forks_count":21,"subscribers_count":18,"default_branch":"main","last_synced_at":"2025-04-09T09:15:43.213Z","etag":null,"topics":["c-sharp","csharp","dotnet","dotnet-core","dynamic-queries","entity-framework","linq"],"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/axelheer.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},"funding":{"custom":"paypal.me/axelheer"}},"created_at":"2014-12-14T12:44:17.000Z","updated_at":"2025-03-10T19:26:50.000Z","dependencies_parsed_at":"2023-12-13T17:56:15.776Z","dependency_job_id":"ced37540-6e11-4ca3-beeb-76cfefba16f5","html_url":"https://github.com/axelheer/nein-linq","commit_stats":null,"previous_names":[],"tags_count":40,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axelheer%2Fnein-linq","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axelheer%2Fnein-linq/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axelheer%2Fnein-linq/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axelheer%2Fnein-linq/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/axelheer","download_url":"https://codeload.github.com/axelheer/nein-linq/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248325077,"owners_count":21084866,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["c-sharp","csharp","dotnet","dotnet-core","dynamic-queries","entity-framework","linq"],"created_at":"2024-08-01T18:00:57.879Z","updated_at":"2025-04-11T01:31:03.885Z","avatar_url":"https://github.com/axelheer.png","language":"C#","funding_links":["paypal.me/axelheer"],"categories":["C# #"],"sub_categories":[],"readme":"NeinLinq\n========\n\n[![Latest package](https://img.shields.io/nuget/v/NeinLinq.svg)](https://www.nuget.org/packages/NeinLinq)\n[![Download tracker](https://img.shields.io/nuget/dt/NeinLinq.svg)](https://www.nuget.org/packages/NeinLinq)\n[![GitHub status](https://github.com/axelheer/nein-linq/workflows/everything/badge.svg)](https://github.com/axelheer/nein-linq/actions)\n[![Code coverage](https://codecov.io/gh/axelheer/nein-linq/branch/main/graph/badge.svg)](https://codecov.io/gh/axelheer/nein-linq)\n\n*NeinLinq* provides helpful extensions for using LINQ providers such as Entity Framework that support only a minor subset of .NET functions, reusing functions, rewriting queries, even making them null-safe, and building dynamic queries using translatable predicates and selectors.\n\nTo support different LINQ implementations, the following flavours are available. Choose at least one.\n\nUse *NeinLinq* for plain LINQ queries:\n\n```ps1\nPM\u003e Install-Package NeinLinq\n```\n\nUse *NeinLinq.Async* for [async](https://github.com/dotnet/reactive/) LINQ queries:\n\n```ps1\nPM\u003e Install-Package NeinLinq.Async\n```\n\nUse *NeinLinq.EntityFramework* for [Entity Framework 6](https://github.com/dotnet/ef6/) LINQ queries:\n\n```ps1\nPM\u003e Install-Package NeinLinq.EntityFramework\n```\n\nUse *NeinLinq.EntityFrameworkCore* for [Entity Framework Core](https://github.com/dotnet/efcore/) LINQ queries:\n\n```ps1\nPM\u003e Install-Package NeinLinq.EntityFrameworkCore\n```\n\n***Note:*** the extension methods described below have different names depending on the chosen package above, in order to avoid some conflicts! For example there are:\n\n- `ToInjectable` (*NeinLinq*)\n- `ToAsyncInjectable` (*NeinLinq.Async*)\n- `ToDbInjectable` (*NeinLinq.EntityFramework*)\n- `ToEntityInjectable` (*NeinLinq.EntityFrameworkCore*)\n\nUsage of specific flavors is encouraged for EF6 / EFCore (otherwise async queries won't work).\n\n***New:***  with Version `5.1.0` the package *NeinLinq.EntityFrameworkCore* introduced an explicit `DbContext` extension for enabling *Lambda injection* globally:\n\n```csharp\n    services.AddDbContext\u003cMyContext\u003e(options =\u003e\n         options.UseSqlOrTheLike(\"...\").WithLambdaInjection());\n```\n\n***Note:*** the call to `WithLambdaInjection` needs to happen *after* the call to `UseSqlOrTheLike`!\n\nLambda injection\n----------------\n\nMany LINQ providers can only support a very minor subset of .NET functionality, they even cannot support our own \"functions\". Say, we implement a simple method `LimitText` and use it within an ordinary LINQ query, which will get translated to SQL through *Entity Framework*...\n\n\u003e *LINQ to Entities does not recognize the method 'System.String LimitText(System.String, Int32)' method, and this method cannot be translated into a store expression.*\n\nThis is what we get; in fact, it's really annoying. We have to scatter our logic between code, that will be translated by any LINQ query provider, and code, that won't. It gets even worse: if some logic is \"translatable\", which is good, we have to copy and paste! Consolidating the code within an ordinary function does not work since the provider is unable to translate this simple method call. Meh.\n\nLet us introduce \"lambda injection\":\n\n```csharp\n[InjectLambda]\npublic static string LimitText(this string value, int maxLength)\n{\n    if (value != null \u0026\u0026 value.Length \u003e maxLength)\n        return value.Substring(0, maxLength);\n    return value;\n}\n\npublic static Expression\u003cFunc\u003cstring, int, string\u003e\u003e LimitText()\n{\n    return (v, l) =\u003e v != null \u0026\u0026 v.Length \u003e l ? v.Substring(0, l) : v;\n}\n\n// -------------------------------------------------------------------\n\nfrom d in data.ToInjectable()\nselect new\n{\n    Id = d.Id,\n    Value = d.Name.LimitText(10)\n}\n```\n\nIf a query is marked as \"injectable\" (`ToInjectable()`) and a function used within this query is marked as \"inject here\" (`[InjectLambda]`), the rewrite engine of *NeinLinq* replaces the method call with the matching lambda expression, which can get translate to SQL or whatever. Thus, we are able to encapsulate unsupported .NET functionality and even create our own. Yay.\n\n```csharp\n[InjectLambda]\npublic static bool Like(this string value, string likePattern)\n{\n    throw new NotImplementedException();\n}\n\npublic static Expression\u003cFunc\u003cstring, string, bool\u003e\u003e Like()\n{\n    return (v, p) =\u003e SqlFunctions.PatIndex(p, v) \u003e 0;\n}\n\n// -------------------------------------------------------------------\n\nfrom d in data.ToInjectable()\nwhere d.Name.Like(\"%na_f%\")\nselect ...\n```\n\nThis is an example of how we can abstract the `SqlFunctions` class of *Entity Framework* to use a (hopefully) nicer `Like` extension method within our query code -- `PatIndex` is likely used to simulate a SQL LIKE statement, why not make it so? We can actually implement the \"ordinary\" method with the help of regular expressions to run our code *without* touching `SqlFunctions` too...\n\n***New:***  with Version `7.0.0` NeinLinq now supports custom providers for the InjectLambdaAttribute. This feature allows you to define your own logic to determine which methods should be considered injectable without explicitly adding `[InjectLambda]` attribute. This is particularly useful when working with external libraries or code you can't modify directly:\n\n```csharp\nvar oldProvider = InjectLambdaAttribute.Provider;\n\nInjectLambdaAttribute.SetAttributeProvider(memberInfo =\u003e \n{\n    // Your custom logic here\n    if (memberInfo.Name.StartsWith(\"ExternalMethod\"))\n    {\n        return new InjectLambdaAttribute(typoef(MyType), nameof(MyType.ExternalMethodExpression));\n    }\n    // fallback to standard provider\n    return oldProvider(memberInfo);\n});\n```\nFinally, let us look at this query using *Entity Framework* or the like:\n\n```csharp\nfrom d in data.ToInjectable()\nlet e = d.RetrieveWhatever()\nwhere d.FulfillsSomeCriteria()\nselect new\n{\n    Id = d.Id,\n    Value = d.DoTheFancy(e)\n}\n\n// -------------------------------------------------------------------\n\n[InjectLambda]\npublic static Whatever RetrieveWhatever(this Entity value)\n{\n    throw new NotImplementedException();\n}\n\npublic static Expression\u003cFunc\u003cEntity, Whatever\u003e\u003e RetrieveWhatever()\n{\n    return d =\u003e d.Whatevers.FirstOrDefault(e =\u003e ...);\n}\n\n[InjectLambda]\npublic static bool FulfillsSomeCriteria(this Entity value)\n{\n    throw new NotImplementedException();\n}\n\npublic static Expression\u003cFunc\u003cEntity, bool\u003e\u003e FulfillsSomeCriteria()\n{\n    return d =\u003e ...\n}\n\n[InjectLambda]\npublic static decimal DoTheFancy(this Entity value, Whatever other)\n{\n    throw new NotImplementedException();\n}\n\npublic static Expression\u003cFunc\u003cEntity, Whatever, decimal\u003e\u003e DoTheFancy()\n{\n    return (d, e) =\u003e ...\n}\n```\n\nThe methods `RetrieveWhatever`, `FulfillsSomeCriteria` and `DoTheFancy` should be marked accordingly, using the attribute `[InjectLambda]` or just the simple convention \"same class, same name, matching signature\" (which requires the class to be green listed by the way). And the call `ToInjectable` can happen anywhere within the LINQ query chain, so we don't have to pollute our business logic.\n\n***Note:*** code duplication should not be necessary. The ordinary method can just compile the expression, ideally only once. A straightforward solution can look like the following code sample (it's possible to encapsulate / organize this stuff however sophisticated it seems fit, *NeinLinq* has no specific requirements; feel free to use the build-in \"Expression Cache\" or build something fancy...):\n\n```csharp\npublic static CachedExpression\u003cFunc\u003cstring, int, string\u003e\u003e LimitTextExpr { get; }\n    = new((v, l) =\u003e v != null \u0026\u0026 v.Length \u003e l ? v.Substring(0, l) : v)\n\n[InjectLambda]\npublic static string LimitText(this string value, int maxLength)\n    =\u003e LimitTextExpr.Compiled(value, maxLength);\n```\n\n***Advanced:*** that works with instance methods too, so the actual expression code is able to retrieve additional data. Even interfaces and / or base classes can be used to abstract all the things. Thus, we can declare an interface / base class without expressions, but provide the expression to inject using inheritance.\n\n```csharp\npublic class ParameterizedFunctions\n{\n    private readonly int narf;\n\n    public ParameterizedFunctions(int narf)\n    {\n        this.narf = narf;\n    }\n\n    [InjectLambda(\"FooExpr\")]\n    public string Foo()\n    {\n        ...\n    }\n\n    public Expression\u003cFunc\u003cstring\u003e\u003e FooExpr()\n    {\n        ... // use the narf!\n    }\n}\n\n// -------------------------------------------------------------------\n\npublic interface IFunctions\n{\n    [InjectLambda]\n    string Foo(Entity value); // use abstraction for queries\n}\n\npublic class Functions : IFunctions\n{\n    [InjectLambda]\n    public string Foo(Entity value)\n    {\n        ...\n    }\n\n    public Expression\u003cFunc\u003cEntity, string\u003e\u003e Foo()\n    {\n        ...\n    }\n}\n\n```\n\n***Note***: injecting instance methods is not as efficient as injecting static methods. Just don't use the former ones, if not really necessary. Furthermore, injecting instance methods of a sealed type reduces the overhead a bit, since there are more things that only need to be done once. Okay, nothing new to say here.\n\n***One more thing:*** to be more hacky and use less extension method ceremony, it's possible to inject properties directly within in models.\n\n```csharp\npublic class Model\n{\n    public double Time { get; set; }\n\n    public double Distance { get; set; }\n\n    [InjectLambda]\n    public double Velocity =\u003e Distance / Time;\n\n    public static Expression\u003cFunc\u003cModel, double\u003e\u003e VelocityExpr =\u003e v =\u003e v.Distance / v.Time;\n}\n```\n\nAgain, instead of placing `[InjectLambda]` on everything it's possible to add all the models to the green-list while calling `ToInjectable`.\n\nNull-safe queries\n-----------------\n\nWe are writing the year 2024 and still have to worry about null values.\n\nHowsoever, we got used to it and we are fine. But writing queries in C# loaded with null checks doesn't feel right, it just looks awful, the translated SQL even gets worse. A LINQ query just for SQL dbs can spare these null checks, a LINQ query just for in-memory calculations must include them. And a LINQ query for both has a problem (unit testing?), which *NeinLinq* tries to solve.\n\nThe following query may trigger null references:\n\n```csharp\nfrom a in data\norderby a.SomeInteger\nselect new\n{\n    Year = a.SomeDate.Year,\n    Integer = a.SomeOther.SomeInteger,\n    Others = from b in a.SomeOthers\n             select b.SomeDate.Month,\n    More = from c in a.MoreOthers\n           select c.SomeOther.SomeDate.Day\n}\n```\n\nWhile the following query *should* not:\n\n```csharp\nfrom a in data\nwhere a != null\norderby a.SomeInteger\nselect new\n{\n    Year = a.SomeDate.Year,\n    Integer = a.SomeOther != null\n            ? a.SomeOther.SomeInteger\n            : 0,\n    Others = a.SomeOthers != null\n           ? from b in a.SomeOthers\n             select b.SomeDate.Month\n           : null,\n    More = a.MoreOthers != null\n         ? from c in a.MoreOthers\n           select c.SomeOther != null\n                ? c.SomeOther.SomeDate.Day\n                : 0\n         : null\n}\n```\n\nMaybe we've forgot some check? Or we can relax thanks to *NeinLinq*:\n\n```csharp\nfrom a in data.ToNullsafe()\norderby a.SomeInteger\nselect new\n{\n    Year = a.SomeDate.Year,\n    Integer = a.SomeOther.SomeInteger,\n    Others = from b in a.SomeOthers\n             select b.SomeDate.Month,\n    More = from c in a.MoreOthers\n           select c.SomeOther.SomeDate.Day\n}\n```\n\nAs with every `ToWhatever` helper within *NeinLinq*, `ToNullsafe` can be called wherever within the LINQ query chain.\n\nPredicate translator\n--------------------\n\nMany data driven applications need to build some kind of dynamic queries. This can lead to dirty string manipulations, complex expression tree plumbing, or a combination of those. Simple *and*/*or*-conjunctions are already solved within other libraries, but conjunctions of \"foreign\" predicates are not that easy.\n\nLet us think of three entities: Academy has Courses, Courses has Lectures.\n\n```csharp\nExpression\u003cFunc\u003cCourse, bool\u003e\u003e p = c =\u003e ...\nExpression\u003cFunc\u003cCourse, bool\u003e\u003e q = c =\u003e ...\n\ndb.Courses.Where(p.And(q))...\n```\n\nOk, we already know that.\n\n```csharp\nExpression\u003cFunc\u003cAcademy, bool\u003e\u003e p = a =\u003e ...\n\ndb.Courses.Where(p.Translate()\n                  .To\u003cCourse\u003e(c =\u003e c.Academy))...\n```\n\nWe now can translate a (combined) predicate for a parent entity...\n\n```csharp\nExpression\u003cFunc\u003cLecture, bool\u003e\u003e p = l =\u003e ...\n\ndb.Courses.Where(p.Translate()\n                  .To\u003cCourse\u003e((c, q) =\u003e c.Lectures.Any(q)))...\n```\n\n..and even for child entities.\n\nLet us use all of this as a windup:\n\n```csharp\nIEnumerable\u003cExpression\u003cFunc\u003cAcademy, bool\u003e\u003e\u003e predicatesForAcademy = ...\nIEnumerable\u003cExpression\u003cFunc\u003cCourse, bool\u003e\u003e\u003e predicatesForCourse = ...\nIEnumerable\u003cExpression\u003cFunc\u003cLecture, bool\u003e\u003e\u003e predicatesForLecture = ...\n\nvar singlePredicateForAcademy =\n    predicatesForAcademy.Aggregate((p, q) =\u003e p.And(q));\nvar singlePredicateForCourse =\n    predicatesForCourse.Aggregate((p, q) =\u003e p.And(q));\nvar singlePredicateForLecture =\n    predicatesForLecture.Aggregate((p, q) =\u003e p.And(q));\n\nvar academyPredicateForCourse =\n    singlePredicateForAcademy.Translate()\n                             .To\u003cCourse\u003e(c =\u003e c.Academy);\nvar coursePredicateForCourse =\n    singlePredicateForCourse; // the hard one ^^\nvar lecturePredicateForCourse =\n    singlePredicateForLecture.Translate()\n                             .To\u003cCourse\u003e((c, p) =\u003e c.Lectures.Any(p));\n\nvar finalPredicate =\n    academyPredicateForCourse.And(coursePredicateForCourse)\n                             .And(lecturePredicateForCourse);\n\ndb.Courses.Where(finalPredicate)...\n```\n\nIn addition to it, no *Invoke* is used to achieve that: many LINQ providers do not support it (*Entity Framework*, i'm looking at you...), so this solution should be quite compatible.\n\nSelector translator\n-------------------\n\nAs with predicates selectors need some love too. If we've an existing selector for some base type and want to reuse this code for one or more concrete types, we're forced to copy and paste again. Don't do that!\n\nLet us think of two entities (Academy and SpecialAcademy) with according Contracts / ViewModels / DTOs / Whatever (AcademyView and SpecialAcademyView).\n\n```csharp\nExpression\u003cFunc\u003cAcademy, AcademyView\u003e\u003e s =\n    a =\u003e new AcademyView { Id = a.Id, Name = a.Name };\nExpression\u003cFunc\u003cSpecialAcademy, SpecialAcademyView\u003e\u003e t =\n    a =\u003e new SpecialAcademyView { Narf = a.Narf };\n```\n\nNote that we omit the *Member bindings* of the first selector within the second one. Don't repeat yourself, remember?\n\n```csharp\ndb.Academies.OfType\u003cSpecialAcademy\u003e()\n            .Select(s.Translate()\n                     .Cross\u003cSpecialAcademy\u003e()\n                     .Apply(t));\n```\n\nAlthough there're more options, the common scenario can look that way: reuse the base selector, start it's translation (type inference), say where to start (no type inference), and finally apply the additional selector (type inference, again).\n\nNow let us consider parent / child relations (Academy and Course).\n\n```csharp\nExpression\u003cFunc\u003cAcademy, AcademyView\u003e\u003e s =\n    a =\u003e new AcademyView { Id = a.Id, Name = a.Name };\nExpression\u003cFunc\u003cCourse, CourseView\u003e\u003e t =\n    c =\u003e new CourseView { Id = c.Id, Name = c.Name };\n\ndb.Courses.Select(s.Translate()\n                   .Cross\u003cCourse\u003e(c =\u003e c.Academy)\n                   .Apply(c =\u003e c.Academy, t));\n\ndb.Academies.Select(t.Translate()\n                     .Cross\u003cAcademy\u003e((a, v) =\u003e a.Courses.Select(v))\n                     .Apply(a =\u003e a.Courses, s));\n```\n\nAgain, apart from other options, we can translate from parent to child: reuse the parent selector, start it's translation, say where to start (given the path to it's parent entity), and finally apply the additional selector (given the path to it's parent \"view\"). And we can translate the other way too: reuse the child selector, start it's translation, say where to start (given an expression to select the children), and finally apply the additional selector...\n\nTo be more flexible the \"Source translation\" / \"Result translation\" can be used individually:\n\n```csharp\nExpression\u003cFunc\u003cAcademy, AcademyView\u003e\u003e selectAcademy =\n    a =\u003e new AcademyView { Id = a.Id, Name = a.Name };\n\nvar selectCourseWithAcademy =\n    selectAcademy.Translate()\n                 .Source\u003cCourse\u003e(c =\u003e c.Academy)\n                 .Translate()\n                 .Result\u003cCourseView\u003e(c =\u003e c.Academy)\n                 .Apply(a =\u003e new CourseView\n                 {\n                     Id = a.Id,\n                     Name = a.Name\n                 });\n```\n\n***Note:*** to be less verbose \"Source translation\" / \"Result translation\" can be used within a single bloated statement, if appropriate:\n\n```csharp\nExpression\u003cFunc\u003cCourse, CourseView\u003e\u003e selectCourse =\n    c =\u003e new CourseView { Id = c.Id, Name = c.Name };\n\nvar selectAcademyWithCourses =\n    selectCourse.Translate()\n                .To\u003cAcademy, AcademyView\u003e((a, v) =\u003e new AcademyView\n                {\n                    Id = a.Id,\n                    Name = a.Name,\n                    Courses = a.Courses.Select(v)\n                })\n```\n\n***Note:*** for parent / child relations the less dynamic but (maybe) more readable *Lambda injection* is also an option: just encapsulate the selector as a nice extension method.\n\nFunction substitution\n---------------------\n\nThis is a really dead simple one. Maybe we should've started here.\n\nJust think of helper functions like the `SqlFunctions` class provided by *Entity Framework*. And we need to replace the whole class for unit testing or whatsoever.\n\n```csharp\nvar query = ...\n\nCallCodeUsingSqlFunctions(query\n    .ToSubstitution(typeof(SqlFunctions), typeof(SqlCeFunctions)));\nCallCodeUsingSqlFunctions(query\n    .ToSubstitution(typeof(SqlFunctions), typeof(FakeFunctions)));\n...\n```\n\nThat's it.\n\nCustom query manipulation\n-------------------------\n\nOkay, you can use the generic rewrite mechanism of this library to intercept LINQ queries with your own *Expression visitor*. The code behind the substitution above should provide a good example.\n\nDynamic query filtering / sorting\n---------------------------------\n\nAt some point it may be necessary to filter / sort an almost ready query based on user input, which is by its nature not type safe but text based. To handle these scenarios as well a (very) simple helper is included.\n\n```csharp\nvar query = data.Where(\"Name.Length\", DynamicCompare.GreaterThan, \"7\")\n                .OrderBy(\"Name\").ThenBy(\"Number\", descending: true);\n```\n\nIt's possible to combine this stuff with the predicate translations above.\n\n```csharp\nvar p = DynamicQuery.CreatePredicate\u003cWhatever\u003e(\"Name\", \"Contains\", \"p\");\nvar q = DynamicQuery.CreatePredicate\u003cWhatever\u003e(\"Name\", \"Contains\", \"q\");\n\nvar query = data.Where(p.Or(q));\n```\n\n***Note:*** if you're seeking a possibility to create complex queries based on string manipulation, this won't help. The goal of this library is to stay type safe as long as possible.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faxelheer%2Fnein-linq","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faxelheer%2Fnein-linq","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faxelheer%2Fnein-linq/lists"}