efcore icon indicating copy to clipboard operation
efcore copied to clipboard

Support MemberMemberBinding

Open roji opened this issue 6 years ago • 8 comments

This tracks adding support for MemberMemberBinding in our query pipeline (first discussed in #16791).

Some preliminary work was done and is available in https://github.com/roji/EntityFrameworkCore/tree/MemberMemberBinding.

roji avatar Jul 31 '19 11:07 roji

Do you happen to have an approximate timeline for this feature request? And do you plan to support MemberListBinding?

We are using protobuf-generated C# classes as DTOs and having trouble projecting to repeated fields (i.e., lists) due to RepeatedField<T> fields not having setters:

context.Users.Select(u => new UserProto {
  Roles = {
    u.Roles.Select(...),
  },
}).ToList();

This doesn't work due to EFCore not supporting MemberListBinding IIUC

erdalsivri avatar Jun 03 '22 23:06 erdalsivri

@erdalsivri We use votes (👍) on issues as a rough measure of customer demand for issues, which then feeds into the planning process. This issue doesn't have any votes, which means there are more than 500 issues ahead of it in the voting.

ajcvickers avatar Jun 06 '22 11:06 ajcvickers

Do you happen to have an approximate timeline for this feature request? And do you plan to support MemberListBinding?

We are using protobuf-generated C# classes as DTOs and having trouble projecting to repeated fields (i.e., lists) due to RepeatedField<T> fields not having setters:

context.Users.Select(u => new UserProto {
  Roles = {
    u.Roles.Select(...),
  },
}).ToList();

This doesn't work due to EFCore not supporting MemberListBinding IIUC

I have same issue with you LOL

auvansang avatar Oct 04 '23 08:10 auvansang

Currently, I found the work around solution:

I create use partial class with the same name from the generated. Then I create a new constructor that accept the tag list args.

public sealed partial class PostResponse
{
    public PostResponse(IEnumerable<string> tags): base()
    {
        Tags.AddRange(tags);
    }
}

And the projection will look like bellow:

x => new PostResponse(x.TagSlugs)
  {
      Id = x.Id.ToString(),
      Title = x.Title,
      Slug = x.Slug,
      Excerpt = x.Excerpt,
      Content = x.Content,
  }

you can also use the constructor like bellow, but it will cause of getting all columns

public PostResponse(IEnumerable<Tag> tags) : base()
{
    Tags.AddRange(tags.Select(x => x.Slug));
}

auvansang avatar Oct 04 '23 08:10 auvansang

Do you happen to have an approximate timeline for this feature request? And do you plan to support MemberListBinding?

We are using protobuf-generated C# classes as DTOs and having trouble projecting to repeated fields (i.e., lists) due to RepeatedField<T> fields not having setters:

context.Users.Select(u => new UserProto {
  Roles = {
    u.Roles.Select(...),
  },
}).ToList();

This doesn't work due to EFCore not supporting MemberListBinding IIUC

Running into the same use-case with auto generated gRPC classes

jsheetzmt avatar Oct 05 '23 15:10 jsheetzmt

Using the approach outlined in https://github.com/dotnet/efcore/issues/16867#issuecomment-1746413846, was working fine in EF Core 8, but now throws an exception in EF Core 9 RC

var entities= await dbContext.Entities
    .AsNoTracking()
    .Skip(pageIndex * pageSize)
    .Take(pageSize)
    .OrderBy(a => a.Prop1)
    .Select(a => new Protobuf.Entity(a.Values.Select(v => v.LinkedEntity.Name!))
    {
        Prop1= a.Prop1,
        Prop2 = a.Prop2 ,
    })
    .ToListAsync();

exception thrown

System.NullReferenceException: Object reference not set to an instance of an object.
   at lambda_method1969(Closure, QueryContext, DbDataReader, ResultContext, SingleQueryResultCoordinator)
   at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.MoveNextAsync()
   at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)

versions in Directory.Package.props

<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="9.0.0-rc.2.24474.1"/>
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.0-rc.2.24474.1"/>
<PackageVersion Include="Microsoft.EntityFrameworkCore.Proxies" Version="9.0.0-rc.2.24474.1"/>
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.0-rc.2.24474.1"/>
<PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.0-rc.2"/>

russcam avatar Oct 17 '24 13:10 russcam

Hey @russcam 👋

MemberMemberBinding should indeed be working in the final select (client evaluation), this issue is more about enabling it in other contexts... If EF 9 regressed support for this, that's probably something we should look at - can you please open a separate issue with a minimal repro?

roji avatar Oct 17 '24 17:10 roji

Apologies for conflating @roji, I've opened https://github.com/dotnet/efcore/issues/34934 with a minimal repro.

russcam avatar Oct 18 '24 01:10 russcam