Giter Site home page Giter Site logo

Comments (3)

AntonC9018 avatar AntonC9018 commented on June 2, 2024

Just tried making a hack to make it work:

#nullable enable
using System;
using System.Linq;
using System.Reflection;
using EntityFrameworkCore.Projectables.Infrastructure.Internal;
using LinqToDB.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.EntityFrameworkCore.Query.Internal;

#pragma warning disable EF1001 // Internal API use

// https://github.com/linq2db/linq2db.EntityFrameworkCore/issues/364
public sealed class LinqToDbEfCoreImplWithProjectableSupport : LinqToDBForEFToolsImplDefault
{
    public static readonly LinqToDbEfCoreImplWithProjectableSupport Instance = new();

    private static readonly FieldInfo QueryCompilerField;
    private static readonly FieldInfo QueryContextFactoryField;
    private static readonly Func<RelationalQueryContextFactory, QueryContextDependencies> GetDependenciesFunc;
    // https://github.com/koenbeuk/EntityFrameworkCore.Projectables/blob/4a8390565d5a8987ea6612c5c555afd35e2266dc/src/EntityFrameworkCore.Projectables/Infrastructure/Internal/CustomQueryCompiler.cs#L16
    private static readonly FieldInfo ProjectablesDecoratedQueryField;

    static LinqToDbEfCoreImplWithProjectableSupport()
    {
        FieldInfo GetPrivateField(Type type, string name)
        {
            var field = type.GetField(name, BindingFlags.NonPublic | BindingFlags.Instance);
            if (field == null)
                throw new LinqToDBForEFToolsException($"Can't find {name} field.");
            return field;
        }
        QueryCompilerField = GetPrivateField(typeof(EntityQueryProvider), "_queryCompiler");
        QueryContextFactoryField = GetPrivateField(typeof(QueryCompiler), "_queryContextFactory");
        ProjectablesDecoratedQueryField = GetPrivateField(typeof(CustomQueryCompiler), "_decoratedQueryCompiler");

        {
            var dependenciesProperty = typeof(RelationalQueryContextFactory)
                .GetProperty("Dependencies", BindingFlags.NonPublic | BindingFlags.Instance)!
                ?? throw new LinqToDBForEFToolsException("Can't find Dependencies property.");
            var getDependenciesMethod = dependenciesProperty
                .GetMethod!
                ?? throw new LinqToDBForEFToolsException("Can't find Dependencies property getter.");
            GetDependenciesFunc = getDependenciesMethod
                .CreateDelegate<Func<RelationalQueryContextFactory, QueryContextDependencies>>();
        }
    }

    public override DbContext? GetCurrentContext(IQueryable query)
    {
        var compiler = QueryCompilerField.GetValue(query.Provider);
        while (true)
        {
            if (compiler is QueryCompiler efCoreQueryCompiler)
            {
                if (QueryContextFactoryField.GetValue(efCoreQueryCompiler) is not RelationalQueryContextFactory queryContextFactory)
                    throw new LinqToDBForEFToolsException("LinqToDB Tools for EFCore support only Relational Databases.");
                var dependencies = GetDependenciesFunc(queryContextFactory);
                return dependencies.CurrentContext.Context;
            }
            if (compiler is CustomQueryCompiler projectableCompiler)
            {
                compiler = ProjectablesDecoratedQueryField.GetValue(projectableCompiler);
                continue;
            }
            return null;
        }
    }
}

And the set that as the implementation in Main:

LinqToDBForEFTools.Initialize();
LinqToDBForEFTools.Implementation = LinqToDbEfCoreImplWithProjectableSupport.Instance;

However, it still kept its own instance? How do I make it work? Ideally Initialize should take a parameter with the impl, perhaps? For some reason the implementation property doesn't work.

from linq2db.entityframeworkcore.

MaceWindu avatar MaceWindu commented on June 2, 2024

@sdanyliv , it looks to me that LinqToDBForEFTools.Implementation assignment should trigger re-initialize, which is not possible with current code due to Lazy already triggered.

from linq2db.entityframeworkcore.

AntonC9018 avatar AntonC9018 commented on June 2, 2024

@sdanyliv , it looks to me that LinqToDBForEFTools.Implementation assignment should trigger re-initialize, which is not possible with current code due to Lazy already triggered.

No, sorry, it works. I was instantiating the wrong class, that's why. I've fixed the code in the comment.

from linq2db.entityframeworkcore.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.