You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
awaitcontext.Foos.ExecuteUpdateAsync(s =>s.SetProperty(e =>e.Address, b =>newAddress(b.Address.Line2,"B")));
System.InvalidOperationException: The LINQ expression 'DbSet<Foo>()
.ExecuteUpdate(s => s.SetProperty<Address>(
propertyExpression: e => e.Address,
valueExpression: b => new Address(
b.Address.Line2,
"B"
)))' could not be translated. Additional information: The following lambda argument to 'SetProperty' does not represent a valid value: 'b => new Address(
b.Address.Line2,
"B"
)'. See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.
Full code:
using(varcontext=newSomeDbContext()){awaitcontext.Database.EnsureDeletedAsync();awaitcontext.Database.EnsureCreatedAsync();context.AddRange(newFoo{Address=newAddress("A","B")});awaitcontext.SaveChangesAsync();}using(varcontext=newSomeDbContext()){// Worksawaitcontext.Foos.ExecuteUpdateAsync(s =>s.SetProperty(e =>e.Address,newAddress("B","A")));// Throwsawaitcontext.Foos.ExecuteUpdateAsync(s =>s.SetProperty(e =>e.Address, b =>newAddress(b.Address.Line2,"B")));}publicclassSomeDbContext:DbContext{publicDbSet<Foo>Foos=>Set<Foo>();protectedoverridevoidOnConfiguring(DbContextOptionsBuilderoptionsBuilder)=>optionsBuilder.UseSqlServer(@"Data Source=localhost;Database=One;Integrated Security=True;Trust Server Certificate=True").LogTo(Console.WriteLine).EnableSensitiveDataLogging();}publicclassFoo{publicintId{get;set;}publicrequiredAddressAddress{get;set;}}[ComplexType]publicrecordAddress(stringLine1,stringLine2);
The text was updated successfully, but these errors were encountered:
Confirmed this as a bug in our ExecuteUpdate complex property assignment feature (#32058, done for 9.0).
The general problem is that we don't translate MemberInitExpression - which makes sense as there's no SQL equivalent for it. However, we do support it in some specific scenarios, e.g. equality comparison for this does work (Where(e => e.Address == new Address { Line1 = b.Address.Line1, Line2 = "foo }) - this is because there's specific fallback logic that kicks in when translation fails, which handles MemberInitExpression. Another important case is that MemberInitExpression can be projected out via Select(), and later selected again.
The general theme here is that although MemberInitExpression isn't really translatable, it's still OK as a temporary thing during translation, where whatever is composed on top may make it valid; conceptually it's a bit similar to the situation with GroupBy() before we added support for final GroupBy - although the tree is temporarily invalid, further composition may make it valid again.
So we can introduce a new SqlExpression node, representing a temporary MemberInitExpression translation, and identify that and do the appropriate thing (but if the end tree has such a node, we throw e.g. in SQL generation). The less architectural alternative is to change things around in the ExecuteUpdate logic to handle translation failure and MemberInitExpression, similar to what we're already doing in complex type equality.
This is fine:
This throws:
Full code:
The text was updated successfully, but these errors were encountered: