aqua - Remote.Linq.EntityFramework 7.2.0-alpha-004

Remote linq extensions for entity framework. Use this package to execute remote queries using EF6.

PM> Install-Package Remote.Linq.EntityFramework -Version 7.2.0-alpha-004 -Source https://www.myget.org/F/aqua/api/v3/index.json

Copy to clipboard

> nuget.exe install Remote.Linq.EntityFramework -Version 7.2.0-alpha-004 -Source https://www.myget.org/F/aqua/api/v3/index.json

Copy to clipboard

> dotnet add package Remote.Linq.EntityFramework --version 7.2.0-alpha-004 --source https://www.myget.org/F/aqua/api/v3/index.json

Copy to clipboard
<PackageReference Include="Remote.Linq.EntityFramework" Version="7.2.0-alpha-004" />
Copy to clipboard
source https://www.myget.org/F/aqua/api/v3/index.json

nuget Remote.Linq.EntityFramework  ~> 7.2.0-alpha-004
Copy to clipboard

> choco install Remote.Linq.EntityFramework --version 7.2.0-alpha-004 --source https://www.myget.org/F/aqua/api/v2

Copy to clipboard
Import-Module PowerShellGet
Register-PSRepository -Name "aqua" -SourceLocation "https://www.myget.org/F/aqua/api/v2"
Install-Module -Name "Remote.Linq.EntityFramework" -RequiredVersion "7.2.0-alpha-004" -Repository "aqua" -AllowPreRelease
Copy to clipboard

Browse the sources in this package using Visual Studio or WinDbg by configuring the following symbol server URL: https://www.myget.org/F/aqua/api/v2/symbolpackage/


Remote.Linq

Github Workflow

branch AppVeyor Travis CI Codecov.io Codacy CodeFactor License
main AppVeyor Build Status Travis Build Status codecov Codacy CodeFactor GitHub license
package nuget myget
Remote.Linq NuGet Badge MyGet Pre Release
Remote.Linq.Async.Queryable NuGet Badge MyGet Pre Release
Remote.Linq.EntityFramework NuGet Badge MyGet Pre Release
Remote.Linq.EntityFrameworkCore NuGet Badge MyGet Pre Release
Remote.Linq.Newtonsoft.Json NuGet Badge MyGet Pre Release
Remote.Linq.protobuf-net NuGet Badge MyGet Pre Release
Remote.Linq.Text.Json NuGet Badge MyGet Pre Release

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, 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 allowing LINQ queries defined on a client to be executed on a remote server.

Write operations (insert/update/delete) have to be implemented by other means if needed. InfoCarrier.Core 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().ConfigureAwait(false);

// 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.ConfigureAwait(false))
{
}

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

See MS tutorial on async streams for more info.

Remote.Linq.Async.Queryable

Provides interoperability with Interactive Extensions (Ix.NET / System.Linq.Async.Queryable).

How to Use

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

Remote.Linq.EntityFramework / Remote.Linq.EntityFrameworkCore

Remote linq extensions for Entity Framework and Entity Framework Core.

Use this package when using features specific to EF6 and EF Core:

  • Apply eager-loading (Include-expressions)

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

How to Use

Client Code Sample

Query blogs including posts and owner

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 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 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);
  • .NETFramework 4.6.2
    • EntityFramework (>= 6.4.4)
    • Remote.Linq (>= 7.2.0-alpha-004)
  • .NETStandard 2.1
    • EntityFramework (>= 6.4.4)
    • Remote.Linq (>= 7.2.0-alpha-004)
  • .NETFramework 4.6.2: 4.6.2.0
  • .NETStandard 2.1: 2.1.0.0

Owners

Christof Senn

Authors

Christof Senn

Project URL

https://github.com/6bee/Remote.Linq

License

MIT

Tags

LINQ,expression-tree,lambda,dynamic,remote,remote-query,multi-tier,n-tier,fluent-interface,entity-framework,ef

Info

6 total downloads
2 downloads for version 7.2.0-alpha-004
Download (65.47 KB)
Download symbols (104.34 KB)
Found on the current feed only

Package history

Version Size Last updated Downloads Mirrored?
7.2.0-alpha-004 65.47 KB Wed, 20 Dec 2023 22:13:58 GMT 2
7.2.0-alpha-003 65.56 KB Wed, 13 Dec 2023 10:30:30 GMT 1
7.2.0-alpha-002 65.6 KB Thu, 07 Dec 2023 15:26:53 GMT 1
7.2.0-alpha-001 39.98 KB Wed, 29 Mar 2023 17:33:33 GMT 2