|
8 | 8 | using System.Reflection;
|
9 | 9 | using System.Threading;
|
10 | 10 | using System.Threading.Tasks;
|
| 11 | +using JetBrains.Annotations; |
11 | 12 | using Microsoft.EntityFrameworkCore.ChangeTracking.Internal;
|
12 | 13 | using Microsoft.EntityFrameworkCore.Diagnostics;
|
13 | 14 | using Microsoft.EntityFrameworkCore.Infrastructure;
|
@@ -322,6 +323,9 @@ private static readonly MethodInfo _startTrackingMethodInfo
|
322 | 323 | = typeof(QueryContext).GetRequiredMethod(
|
323 | 324 | nameof(QueryContext.StartTracking), typeof(IEntityType), typeof(object), typeof(ValueBuffer));
|
324 | 325 |
|
| 326 | + private static readonly MethodInfo _createNullKeyValueInNoTrackingQuery |
| 327 | + = typeof(EntityMaterializerInjectingExpressionVisitor).GetRequiredDeclaredMethod(nameof(CreateNullKeyValueInNoTrackingQuery)); |
| 328 | + |
325 | 329 | private readonly IEntityMaterializerSource _entityMaterializerSource;
|
326 | 330 | private readonly QueryTrackingBehavior _queryTrackingBehavior;
|
327 | 331 | private readonly bool _queryStateMananger;
|
@@ -456,16 +460,38 @@ private Expression ProcessEntityShaper(EntityShaperExpression entityShaperExpres
|
456 | 460 | {
|
457 | 461 | if (primaryKey != null)
|
458 | 462 | {
|
459 |
| - expressions.Add( |
460 |
| - Expression.IfThen( |
| 463 | + var keyValuesVariable = Expression.Variable(typeof(object[]), "keyValues" + _currentEntityIndex); |
| 464 | + variables.Add(keyValuesVariable); |
| 465 | + expressions.Add(Expression.Assign( |
| 466 | + keyValuesVariable, |
| 467 | + Expression.NewArrayInit( |
| 468 | + typeof(object), |
461 | 469 | primaryKey.Properties.Select(
|
462 |
| - p => Expression.NotEqual( |
463 |
| - valueBufferExpression.CreateValueBufferReadValueExpression(typeof(object), p.GetIndex(), p), |
464 |
| - Expression.Constant(null))) |
465 |
| - .Aggregate((a, b) => Expression.AndAlso(a, b)), |
466 |
| - MaterializeEntity( |
467 |
| - entityShaperExpression, materializationContextVariable, concreteEntityTypeVariable, instanceVariable, |
468 |
| - null))); |
| 470 | + p => valueBufferExpression.CreateValueBufferReadValueExpression(typeof(object), p.GetIndex(), p))))); |
| 471 | + var keyPropertiesCondition = primaryKey.Properties.Select( |
| 472 | + (p, i) => Expression.NotEqual( |
| 473 | + Expression.ArrayIndex(keyValuesVariable, Expression.Constant(i)), |
| 474 | + Expression.Constant(null))) |
| 475 | + .Aggregate((a, b) => Expression.AndAlso(a, b)); |
| 476 | + |
| 477 | + var entityMaterializationCode = MaterializeEntity( |
| 478 | + entityShaperExpression, materializationContextVariable, concreteEntityTypeVariable, instanceVariable, null); |
| 479 | + |
| 480 | + if (entityShaperExpression.IsNullable) |
| 481 | + { |
| 482 | + expressions.Add(Expression.IfThen(keyPropertiesCondition, entityMaterializationCode)); |
| 483 | + } |
| 484 | + else |
| 485 | + { |
| 486 | + expressions.Add(Expression.IfThenElse( |
| 487 | + keyPropertiesCondition, |
| 488 | + entityMaterializationCode, |
| 489 | + Expression.Call( |
| 490 | + _createNullKeyValueInNoTrackingQuery, |
| 491 | + Expression.Constant(entityType), |
| 492 | + Expression.Constant(primaryKey.Properties), |
| 493 | + keyValuesVariable))); |
| 494 | + } |
469 | 495 | }
|
470 | 496 | else
|
471 | 497 | {
|
@@ -603,6 +629,26 @@ private BlockExpression CreateFullMaterializeExpression(
|
603 | 629 |
|
604 | 630 | return Expression.Block(blockExpressions);
|
605 | 631 | }
|
| 632 | + |
| 633 | + [UsedImplicitly] |
| 634 | + private static Exception CreateNullKeyValueInNoTrackingQuery( |
| 635 | + IEntityType entityType, IReadOnlyList<IProperty> properties, object?[] keyValues) |
| 636 | + { |
| 637 | + var index = -1; |
| 638 | + for (var i = 0; i < keyValues.Length; i++) |
| 639 | + { |
| 640 | + if (keyValues[i] == null) |
| 641 | + { |
| 642 | + index = i; |
| 643 | + break; |
| 644 | + } |
| 645 | + } |
| 646 | + |
| 647 | + var property = properties[index]; |
| 648 | + |
| 649 | + throw new InvalidOperationException( |
| 650 | + CoreStrings.InvalidKeyValue(entityType.DisplayName(), property.Name)); |
| 651 | + } |
606 | 652 | }
|
607 | 653 | }
|
608 | 654 | }
|
0 commit comments