Giter Site home page Giter Site logo

Comments (2)

sdanyliv avatar sdanyliv commented on June 9, 2024

Cte implementation in linq2db (should be fxed in upcoming version 6) do not support inheritance. As a workaround you can return PK and materialize joined values. Your query also totally incorrect and I have prepared correct version:

Define intermediate class

class StorageItemCte
{
    public Guid Id { get; set; }
}
var guid = Guid.Parse("84eb9daa-fbcf-464a-a9da-9b1fbc599a72");
using var db = _dbContext.CreateLinqToDBConnection();

var cteQuery = db.GetCte<StorageItemCte>(storageItems =>
    {
        return 
        (
            from si in _dbContext.StorageItems
            where si.Id == guid
            select new StorageItemCte { Id = si.Id }
        )
        .Concat
        (
            from si in _dbContext.StorageItems
            from cte in storageItems.InnerJoin(cte => cte.Id == si.ParentId)
            select new StorageItemCte { Id = si.Id }
        )
    });

var resultQuery = 
    from cte in cteQuery
    from si in _dbContext.StorageItems.InnerJoin(si => si.Id == cte.Id)
    select si;

var res = await result.ToListAsyncLinqToDB();

from linq2db.entityframeworkcore.

neistow avatar neistow commented on June 9, 2024

@sdanyliv Thanks for the quick reply.

Your query also totally incorrect

It should be, I copy-pasted it from docs and just used IDE to convert LINQ to method chain.

I have prepared correct version

Appreciate your help, that would be a valid workaround... unless TPH issues with linq2db again.

First of all, EF core doesn't really like the following way to define discriminator and can't materialize the final result since it doesn't know what "Folder" discriminator is:

modelBuilder.Entity<StorageItem>()
            .HasDiscriminator(x => x.Type);

Usually I define my discriminators through shadow properties, which works:

        modelBuilder.Entity<StorageItem>()
            .HasDiscriminator<string>("__type")
            .HasValue<StorageFolder>("Folder")
            .HasValue<StorageFile>("File")
            .HasValue<StorageEnhFile>("EFile");

...But it seems that linq2db doesn't know about shadow properties from EF, so it throws:

LinqToDB.Linq.LinqException: Inheritance Discriminator is not defined for the 'EfPlayground.Models.StorageItem' hierarchy.
   at LinqToDB.Mapping.EntityDescriptor.InitInheritanceMapping(Action`2 onEntityDescriptorCreated)
   at LinqToDB.Mapping.EntityDescriptor.Init(Action`2 onEntityDescriptorCreated)
   at LinqToDB.Mapping.EntityDescriptor..ctor(MappingSchema mappingSchema, Type type, Action`2 onEntityDescriptorCreated)
   at LinqToDB.Mapping.MappingSchema.<>c.<GetEntityDescriptor>b__98_0(ICacheEntry`2 o, ValueTuple`2 context)
   at LinqToDB.Common.Internal.Cache.CacheExtensions.GetOrCreate[TItem,TKey,TContext](IMemoryCache`2 cache, TKey key, TContext context, Func`3 factory)
   at LinqToDB.Mapping.MappingSchema.GetEntityDescriptor(Type type, Action`2 onEntityDescriptorCreated)
   at LinqToDB.Linq.Builder.TableBuilder.TableContext..ctor(ExpressionBuilder builder, BuildInfo buildInfo, Type originalType)
   at LinqToDB.Linq.Builder.TableBuilder.BuildSequence(ExpressionBuilder builder, BuildInfo buildInfo)
   at LinqToDB.Linq.Builder.ExpressionBuilder.BuildSequence(BuildInfo buildInfo)
   at LinqToDB.Linq.Builder.WhereBuilder.BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
   at LinqToDB.Linq.Builder.MethodCallBuilder.BuildSequence(ExpressionBuilder builder, BuildInfo buildInfo)
   at LinqToDB.Linq.Builder.ExpressionBuilder.BuildSequence(BuildInfo buildInfo)
   at LinqToDB.Linq.Builder.SelectBuilder.BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
   at LinqToDB.Linq.Builder.MethodCallBuilder.BuildSequence(ExpressionBuilder builder, BuildInfo buildInfo)
   at LinqToDB.Linq.Builder.ExpressionBuilder.BuildSequence(BuildInfo buildInfo)
   at LinqToDB.Linq.Builder.SetOperationBuilder.BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
   at LinqToDB.Linq.Builder.MethodCallBuilder.BuildSequence(ExpressionBuilder builder, BuildInfo buildInfo)
   at LinqToDB.Linq.Builder.ExpressionBuilder.BuildSequence(BuildInfo buildInfo)
   at LinqToDB.Linq.Builder.TableBuilder.<>c__DisplayClass11_0.<BuildCteContext>b__1(CteClause cteClause)
   at LinqToDB.Linq.Builder.ExpressionBuilder.BuildCte(Expression cteExpression, Func`2 buildFunc)
   at LinqToDB.Linq.Builder.TableBuilder.BuildCteContext(ExpressionBuilder builder, BuildInfo buildInfo)
   at LinqToDB.Linq.Builder.TableBuilder.BuildSequence(ExpressionBuilder builder, BuildInfo buildInfo)
   at LinqToDB.Linq.Builder.ExpressionBuilder.BuildSequence(BuildInfo buildInfo)
   at LinqToDB.Linq.Builder.SelectManyBuilder.BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
   at LinqToDB.Linq.Builder.MethodCallBuilder.BuildSequence(ExpressionBuilder builder, BuildInfo buildInfo)
   at LinqToDB.Linq.Builder.ExpressionBuilder.BuildSequence(BuildInfo buildInfo)
   at LinqToDB.Linq.Builder.ExpressionBuilder.Build[T]()
   at LinqToDB.Linq.Query`1.CreateQuery(ExpressionTreeOptimizationContext optimizationContext, ParametersContext parametersContext, IDataContext dataContext, Expression expr)
   at LinqToDB.Linq.Query`1.GetQuery(IDataContext dataContext, Expression& expr, Boolean& dependsOnParameters)
   at LinqToDB.Linq.ExpressionQuery`1.GetQuery(Expression& expression, Boolean cache, Boolean& dependsOnParameters)
   at LinqToDB.Linq.ExpressionQuery`1.GetForEachAsync(Action`1 action, CancellationToken cancellationToken)
   at LinqToDB.AsyncExtensions.ToListAsync[TSource](IQueryable`1 source, CancellationToken token)

Perhaps I could've changed my explicit string Type discriminator to enum, so EF would be satisfied, but at this point I think that it's worth to wait for the upcoming LinqToDb version 6 and continue my experiments afterwards.

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.