koenbeuk / EntityFrameworkCore.Projectables

Project over properties and functions in your linq queries
MIT License
260 stars 17 forks source link

allow properties to have a setter. closes #77 #79

Open hahn-kev opened 11 months ago

hahn-kev commented 11 months ago

This adds support for properties to have a getter (and setter), closes #77. Like this:

public int Prop {
    get => Field;
}

I was able to run a generator test and verify this works, however I kept getting a compile error from the generator on the same code for the functional tests. I'm not sure how to fix that one.

hahn-kev commented 11 months ago

It looks like the tests failed because some properties are getting selected automatically when there's no select statement. Since these properties can have a setter they will get automatically selected by EF when there's no select. For example DbSet.Where(u => u.Name = "test).ToList() there's no select here, so EF will select any writable property, this means that the select doesn't get processed by our code and so it selects properties that are actually aliases. I wonder if there's a way that we can tell EF to skip those properties.

hahn-kev commented 11 months ago

I wonder if we can somehow not map any properties with Projectable, for read only properties it's not needed, but for writable properties they need to be marked as Not mapped or ignored by EF.

koenbeuk commented 11 months ago

I wonder if there's a way that we can tell EF to skip those properties.

I would say we want to select these but based on the projectable expression. I would expect Alias to be computed for me if I queried an Entity without an explicit select clause.

koenbeuk commented 11 months ago

We would essentially want to translate:

dbContext.Entity into dbContext.Entity.Select(x => new Entity { Id = x.Id, Alias = x.Alias })

This is not a trivial undertaking. If you want to give it a shot then the translation could be performed in EntityFrameworkCore.Projectables.Services.ProjectableExpressionReplacer by adding and implementing this:


        protected override Expression VisitExtension(Expression node)
        {
            if (node is QueryRootExpression)
            {
                throw new NotImplementedException("Do some magic here to reference projectable properties");
            }

            return node;
        }
``
koenbeuk commented 10 months ago

84 Is another example of an expression that could be closed if we were to rewrite QueryRootExpressions

zoriya commented 10 months ago

If I understood correctly, QueryRootExpression is the initial dbset so dbContext.Entity for your example. If we were to rewrite the root, would all others rewritter become useless, since projectable fields would become available from the new Select clause?

koenbeuk commented 9 months ago

@zoriya No, this would only make it so that all projectable members of the source type will be expanded. A user can still apply additional Select expressions which will essentially cause the rewrite to become a no-op.

hahn-kev commented 9 months ago

I'd be happy if someone wants to take that on, but I don't have time to do that part right now.