SkillAgentSearch skills...

Remote.Linq

Simply LINQ your remote resources...

Install / Use

/learn @6bee/Remote.Linq

README

Remote.Linq

[![GitHub license][lic-badge]][lic-link] [![Github Workflow][pub-badge]][pub-link]

| branch | AppVeyor | Travis CI | Codecov.io | Codacy | CodeFactor | | --- | --- | --- | --- | --- | --- | | main | AppVeyor Build Status | Travis Build Status | codecov | Codacy | CodeFactor |

| package | nuget | myget | | --- | --- | --- | | Remote.Linq | NuGet Badge | MyGet Pre Release | | Remote.Linq.Async.Queryable | [![NuGet Badge][33]][34] | [![MyGet Pre Release][35]][36] | | Remote.Linq.EntityFramework | NuGet Badge | [MyGet Pre Release][20] | | Remote.Linq.EntityFrameworkCore | [![NuGet Badge][21]][22] | [![MyGet Pre Release][23]][24] | | Remote.Linq.Newtonsoft.Json | [![NuGet Badge][25]][26] | [![MyGet Pre Release][27]][28] | | Remote.Linq.protobuf-net | [![NuGet Badge][29]][30] | [![MyGet Pre Release][31]][32] |

Description

Remote.Linq is a small and easy to use - yet very powerful - library to translate LINQ expression trees to strongly typed, serializable expression trees and vice versa. It provides functionality to send arbitrary LINQ queries to a remote service to be applied and executed against any enumerable or queryable data collection.

Building a LINQ interface for custom services is made a breeze by using Remote.Linq.

Features

  • Translate LINQ expressions into serializable expression trees (remote LINQ expression) and vice versa.
  • Build remote single-type query services (paging, sorting, filtering).
  • Build remote complex LINQ query services (arbitrary LINQ query including joins, groupings, aggregations, projections, etc.).

Scope

In contrast to [re-linq][re-linq-repo], this project enables serialization and deserialization of expression trees and applying LINQ expressions to other LINQ providers e.g. linq-to-object, linq-to-entity, etc.

Remote.Linq makes it super easy to implement a service that executes LINQ queries defined on a client against a data source on a remote server.

Write operations (insert/update/delete) have to be implemented by other means if needed. [InfoCarrier.Core][infocarrier-repo] or [EfCore.Client][efcore-client-repo] might be interesting for such scenarios.

How to Use

Check-out Remote.Linq.Samples.sln and samples folder for a number of sample use cases.

Client Code Sample

Implement a repository class to set-up server connection and expose the queryable data sets (IQueryable<>)

public class ClientDataRepository
{
    private readonly Func<Expression, DynamicObject> _dataProvider;

    public RemoteRepository(string uri)
    {
        _dataProvider = expression =>
        {
            // setup service connectivity
            using IQueryService service = CreateServerConnection(uri);
            // send expression to service and get back results
            DynamicObject result = service.ExecuteQuery(expression);
            return result;
        };
    }

    public IRemoteQueryable<Blog> Blogs => RemoteQueryable.Factory.CreateQueryable<Blog>(_dataProvider);
   
    public IRemoteQueryable<Post> Posts => RemoteQueryable.Factory.CreateQueryable<Post>(_dataProvider);
   
    public IRemoteQueryable<User> Users => RemoteQueryable.Factory.CreateQueryable<User>(_dataProvider);
    
    // where IRemoteQueryable<out T> is IQueryable<out T>
}

Use your repository to compose LINQ query and let the data be retrieved from the backend service

var repository = new ClientDataRepository("https://myserver/queryservice");

var myBlogPosts = (
    from blog in repository.Blogs
    from post in blog.Posts
    join owner in repository.Users on blog.OwnerId equals owner.Id
    where owner.login == "hi-its-me"
    select new 
    {
        post.Title,
        post.Date,
        Preview = post.Text.Substring(0, 50)
    }).ToList();

Server Code Sample

Implement the backend service to handle the client's query expression by applying it to a data source e.g. an ORM

public interface IQueryService : IDisposable
{
    DynamicObject ExecuteQuery(Expression queryExpression);
}

public class QueryService : IQueryService
{
    // any linq provider e.g. entity framework, nhibernate, ...
    private IDataProvider _datastore = new ObjectRelationalMapper();

    // you need to be able to retrieve an IQueryable by type
    private Func<Type, IQueryable> _queryableProvider = type => _datastore.GetQueryableByType(type);

    public DynamicObject ExecuteQuery(Expression queryExpression)
    {
        // `Execute` is an extension method provided by Remote.Linq
        // it applies an expression to a data source and returns the result
        return queryExpression.Execute(queryableProvider: _queryableProvider);
    }

    public void Dispose() => _datastore.Dispose();
}

Async Code Sample

IAsyncRemoteQueryable<TEntity> asyncQuery =
  RemoteQueryable.Factory.CreateAsyncQueryable<TEntity>(...);
TEntity[] result = await asyncQuery.ToArrayAsync();

// where interface IAsyncRemoteQueryable<out T> is IRemoteQueryable<out T> is IQueryable<out T>

Async Stream Code Sample

IAsyncRemoteStreamQueryable<TEntity> asyncStreamQuery =
  RemoteQueryable.Factory.CreateAsyncStreamQueryable<TEntity>(...);
await foreach (TEntity item in asyncStreamQuery)
{
}

// where interface IAsyncRemoteStreamQueryable<out T> is IQueryable<out T>

See [MS tutorial on async streams][async-stream-ms-doc] for more info.

Remote.Linq.Async.Queryable

Provides interoperability with Interactive Extensions ([Ix.NET][ix-net-repo] / [System.Linq.Async.Queryable][ix-net-async-queryable-package]).

How to Use

System.Linq.IAsyncQueryable<TEntity> asyncQuery =
  RemoteQueryable.Factory.CreateAsyncQueryable<TEntity>(...);
await foreach (TEntity item in asyncQuery)
{
}

Remote.Linq.EntityFramework / Remote.Linq.EntityFrameworkCore

Remote linq extensions for [Entity Framework][ef6-package] and [Entity Framework Core][efcore-package].

These packages are used on server side to apply queries to EFs DbContext.

The only reason to include one of these packages in a client side project is to enable utilization of query features specific to EF6 and EF Core:

  • Apply eager-loading (Include-expressions)

  • Make use of DB functions</br> e.g. queryable.Where(x => Microsoft.EntityFrameworkCore.EF.Functions.Like(x.Name, "%fruit%"))

How to Use

Client Code Sample

Query blogs including (i.e. eager loading) posts and owners

using var repository = new RemoteRepository();
var blogs = repository.Blogs
    .Include(x => x.Posts)
    .ThenInclude(x => x.Owner)
    .ToList();

Server Code Sample

Execute query on database via EF Core

public DynamicObject ExecuteQuery(Expression queryExpression)
{
    using var dbContext = new DbContext();
    return queryExpression.ExecuteWithEntityFrameworkCore(dbContext);
}

Remote.Linq.Newtonsoft.Json

Provides [Json.NET][json-net-package] serialization settings for Remote.Linq types.

How to Use

// Serialization
TValue value = ...;
JsonSerializerSettings serializerSettings = new JsonSerializerSettings().ConfigureRemoteLinq(); 
string json = JsonConvert.SerializeObject(value, serializerSettings); 
TValue copy = JsonConvert.DeserializeObject<TValue>(json, serializerSettings); 

Remote.Linq.Text.Json

Provides [System.Text.Json][json-text-package] serialization settings for Remote.Linq types.

How to Use

// Serialization
TValue value = ...;
JsonSerializerOptions serializerOptions = new JsonSerializerOptions().ConfigureRemoteLinq();
string json = JsonSerializer.Serialize(value, serializerOptions);
TValue copy = JsonSerializer.Deserialize<TValue>(json, serializerOptions);
// Microsoft.AspNetCore.Hosting [WebHostBuilder]
new WebHostBuilder()
  .ConfigureServices(services => services
    .AddMvcCore()
    .AddJsonOptions(options => options.JsonSerializerOptions.ConfigureRemoteLinq()));
// Microsoft.AspNetCore.Hosting [WebApplicationBuilder]
var builder = WebApplication.CreateBuilder();
builder.Services
  .AddMvcCore()
  .AddJsonOptions(options => options.JsonSerializerOptions.ConfigureRemoteLinq());
// System.Net.Http.HttpClient
TValue value = ...;
Uri uri = ...;
var serializerOptions = new JsonSerializerOptions().ConfigureRemoteLinq();
using var httpClient = new HttpClient();
await httpClient.PostAsJsonAsync(uri, value, serializerOptions);
View on GitHub
GitHub Stars356
CategoryDevelopment
Updated2mo ago
Forks30

Languages

C#

Security Score

100/100

Audited on Feb 3, 2026

No findings