I'm running the code below but getting an exception on YogabandyFee
when running it.
var payoutResult = await _dbContext.StripePayouts
.Where(p => p.StripePayoutId == stripePayoutId)
.Select(p => new { p.GrossAmount, p.TotalTokens, p.NetAmount, p.ReconciledTransfers, p.EditedDate, p.YogabandyFee })
.ExecuteUpdateAsync(setters => setters
.SetProperty(p => p.GrossAmount, grossAmount)
.SetProperty(p => p.TotalTokens, totalTokens)
.SetProperty(p => p.YogabandyFee, p => new YogabandyFee { TotalFee = (grossAmount - p.NetAmount - platformFee) } )
.SetProperty(p => p.ReconciledTransfers, true)
.SetProperty(p => p.EditedDate, DateTime.UtcNow)
);
Can this be done? Can I create a new entry in this type of update?
Here is the error:
System.InvalidOperationException: The LINQ expression 'DbSet() .Where(s => s.StripePayoutId == __stripePayoutId_0) .LeftJoin( inner: DbSet(), outerKeySelector: s => EF.Property(s, "Id"), innerKeySelector: y => EF.Property(y, "StripePayoutId"), resultSelector: (o, i) => new TransparentIdentifier( Outer = o, Inner = i )) .Select(s => new { GrossAmount = s.Outer.GrossAmount, TotalTokens = s.Outer.TotalTokens, NetAmount = s.Outer.NetAmount, ReconciledTransfers = s.Outer.ReconciledTransfers, EditedDate = s.Outer.EditedDate, YogabandyFee = s.Inner }) .ExecuteUpdate(setters => setters.SetProperty( propertyExpression: p => p.GrossAmount, valueExpression: __grossAmount_1).SetProperty( propertyExpression: p => p.TotalTokens, valueExpression: __totalTokens_2).SetProperty( propertyExpression: p => p.ReconciledTransfers, valueExpression: True).SetProperty( propertyExpression: p => p.EditedDate, valueExpression: DateTime.UtcNow).SetProperty( propertyExpression: p => p.YogabandyFee, valueExpression: p => new YogabandyFee{ TotalFee = __grossAmount_1 - p.NetAmount - __platformFee_3 } ))' could not be translated. Additional information: The following lambda argument to 'SetProperty' does not represent a valid property to be set: 'p => p.YogabandyFee'. See https://go.microsoft.com/fwlink/?linkid=2101038 for more information. at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression) at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.Translate(Expression expression) at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.Translate(Expression expression) at Microsoft.EntityFrameworkCore.Query.QueryCompilationContext.CreateQueryExecutor[TResult](Expression query) at Microsoft.EntityFrameworkCore.Storage.Database.CompileQuery[TResult](Expression query, Boolean async) at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore[TResult](IDatabase database, Expression query, IModel model, Boolean async) at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass12_0
1.b__0() at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func
1 compiler) at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.ExecuteAsync[TResult](Expression query, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.ExecuteAsync[TResult](Expression expression, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.RelationalQueryableExtensions.ExecuteUpdateAsync[TSource](IQueryable1 source, Expression
1 setPropertyCalls, CancellationToken cancellationToken) at Functions.ReconcileTransfers.Run(String myQueueItem) in /Users/charles/yogabandy2020/Functions/ReconcileTransfers.cs:line 119
ExecuteUpdateAsync will try to create a SQL query based on the c# code you write. In the c# code, you are trying to update two tables at the same time in the same query. It's not possible. Even with writing your own SQL, most DMBS, don't allow it. (with exception of MySQL)
From your error message
The following lambda argument to 'SetProperty' does not represent a valid property to be set: 'p => p.YogabandyFee'
it seems like the parser is looking for a property instead of an object, so, hence, I tried to set the TotalFee
of the YogabandyFee
:
var payoutResult = await _dbContext.StripePayouts
.Where(p => p.StripePayoutId == stripePayoutId)
.Select(p => new { p.GrossAmount, p.TotalTokens, p.NetAmount, p.ReconciledTransfers, p.EditedDate, p.YogabandyFee })
.ExecuteUpdateAsync(setters => setters
.SetProperty(p => p.GrossAmount, grossAmount)
.SetProperty(p => p.TotalTokens, totalTokens)
.SetProperty(p => p.YogabandyFee.TotalFee, p => grossAmount - p.NetAmount - platformFee )
.SetProperty(p => p.ReconciledTransfers, true)
.SetProperty(p => p.EditedDate, DateTime.UtcNow)
);
And you'll see this error:
Multiple 'SetProperty' invocations refer to different tables ('p => p.YogabandyFee.TotalFee' and 'p => p.EditedDate'). A single 'ExecuteUpdate' call can only update the columns of a single table.
What I'm trying to say is: ExecuteUpdate
can only update one table. I think, the answer to "Can I create a new entry in this type of update?" is no.
My suggestions:
UnitOfWork
- this allows you to do multiple _dbContext
queries in the same transactionYou can also do two separate ExecuteUpdateAsync
, one for each table update, if it's not a performance issue.