koenbeuk / EntityFrameworkCore.Projectables

Project over properties and functions in your linq queries
MIT License
297 stars 20 forks source link

Use Projectable without Select #84

Closed zoriya closed 11 months ago

zoriya commented 1 year ago

Assuming this example:

public record Entity
{
    public int Id { get; set; }

    [Projectable(UseMemberBody = nameof(Computed2))]
    public int Computed1 { get; set; }

    private int Computed2 => Id * 2;
}

I would like this to work:

public void Test()
{
    Entity foo = database.Set<Entity>().First();
    Assert(foo.Computed1 == foo.Id * 2);
}

with a generated query like that:

SELECT e.id, computed1 as e.Id * 2  FROM entities as e LIMIT 1

Right now, this example fails because the generated query is never rewritten. The actual query looks like this:

SELECT e.id, e.computed1 FROM entities as e LIMIT 1

So the SQL provider throws because computed1 is not a valid column.

yinzara commented 11 months ago

I would REALLY love this feature as well.

I'd probably called this "Materialized Projectioables".

I would like the ability to optionally include a projectable property so that it's projected into the primary entity when it's loaded so that I don't need the related data to be included on the entity without having to include the related data.

Take this example:

public class MyEntity
{
   public Guid Id { get; set; }

   public MyOtherEntity MyOtherEntity { get; set; } = null!;
   public Guid MyOtherEntityId { get; set; }

   [Projectable(UseMemberBody(nameof(MyOtherEntityName))
   public string MyOtherEntityNameIncluded { get; set; }

   [Projectable] public string MyOtherEntityName => this.MyOtherEntity.Name;
}

public class MyOtherEntity
{
   public Guid Id { get; set; }
   public string Name { get; set; }
   ... a lot of other properties and potentially nested owned relationships so loading this entity is expensive
}
dbContext.DbSet<MyEntity>.Include(_ => _.MyOtherEntityNameIncluded)
// or maybe something custom
dbContext.DbSet<MyEntity>.Materialize(_ => _.MyOtherEntityNameIncluded)

If I don't have the materialized properties, I would have to o:

dbContext.DbSet<MyEntity>.Include(_ => _.MyOtherEntity)

which is extremely inefficient

zoriya commented 11 months ago

When #86 gets merged, you would not need anything for your .MyOtherEntityNameIncluded to work.

dbContext.DbSet<MyEntity>.First()

would already include your MyOtherEntityNameIncluded.