Skip to content

Commit

Permalink
Missed one situation for Indexed Properties where we need index acces…
Browse files Browse the repository at this point in the history
…s instead of member access. (#15251)
  • Loading branch information
lajones committed Apr 4, 2019
1 parent d5265c7 commit 514fda6
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 3 deletions.
16 changes: 13 additions & 3 deletions src/EFCore/Metadata/Internal/PropertyAccessorsFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,19 @@ private static PropertyAccessors CreateGeneric<TProperty>(IPropertyBase property
Expression.Property(entryParameter, "Entity"),
entityClrType);

currentValueExpression = Expression.MakeMemberAccess(
convertedExpression,
propertyBase.GetMemberInfo(forConstruction: false, forSet: false));
if (propertyBase.IsIndexedProperty())
{
currentValueExpression = Expression.MakeIndex(
convertedExpression,
propertyBase.PropertyInfo,
new [] { Expression.Constant(propertyBase.Name) });
}
else
{
currentValueExpression = Expression.MakeMemberAccess(
convertedExpression,
propertyBase.GetMemberInfo(forConstruction: false, forSet: false));
}

if (currentValueExpression.Type != typeof(TProperty))
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore.ChangeTracking.Internal;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.EntityFrameworkCore.TestUtilities;
using Microsoft.Extensions.DependencyInjection;
using Xunit;

// ReSharper disable InconsistentNaming
namespace Microsoft.EntityFrameworkCore.Metadata.Internal
{
public class PropertyAccessorsFactoryTest
{
[Fact]
public void Can_use_PropertyAccessorsFactory_on_indexed_property()
{
var model = new Model();
var entityType = model.AddEntityType(typeof(IndexedClass));
var id = entityType.AddProperty("Id", typeof(int));
var propertyA = entityType.AddIndexedProperty("PropertyA", typeof(string));

var contextServices = InMemoryTestHelpers.Instance.CreateContextServices(model);
var stateManager = contextServices.GetRequiredService<IStateManager>();
var factory = contextServices.GetRequiredService<IInternalEntityEntryFactory>();

var entity = new IndexedClass();
var entry = factory.Create(stateManager, entityType, entity);

var propertyAccessors = new PropertyAccessorsFactory().Create(propertyA);
Assert.Equal("ValueA", ((Func<InternalEntityEntry, string>)propertyAccessors.CurrentValueGetter)(entry));
Assert.Equal("ValueA", ((Func<InternalEntityEntry, string>)propertyAccessors.OriginalValueGetter)(entry));
Assert.Equal("ValueA", ((Func<InternalEntityEntry, string>)propertyAccessors.PreStoreGeneratedCurrentValueGetter)(entry));
Assert.Equal("ValueA", ((Func<InternalEntityEntry, string>)propertyAccessors.RelationshipSnapshotGetter)(entry));

var valueBuffer = new ValueBuffer(new object[] { 1, "ValueA" });
Assert.Equal("ValueA", ((Func<ValueBuffer, object>)propertyAccessors.ValueBufferGetter)(valueBuffer));
}

[Fact]
public void Can_use_PropertyAccessorsFactory_on_non_indexed_property()
{
var model = new Model();
var entityType = model.AddEntityType(typeof(NonIndexedClass));
var id = entityType.AddProperty("Id", typeof(int));
var propA = entityType.AddProperty("PropA", typeof(string));

var contextServices = InMemoryTestHelpers.Instance.CreateContextServices(model);
var stateManager = contextServices.GetRequiredService<IStateManager>();
var factory = contextServices.GetRequiredService<IInternalEntityEntryFactory>();

var entity = new NonIndexedClass();
var entry = factory.Create(stateManager, entityType, entity);

var propertyAccessors = new PropertyAccessorsFactory().Create(propA);
Assert.Equal("ValueA", ((Func<InternalEntityEntry, string>)propertyAccessors.CurrentValueGetter)(entry));
Assert.Equal("ValueA", ((Func<InternalEntityEntry, string>)propertyAccessors.OriginalValueGetter)(entry));
Assert.Equal("ValueA", ((Func<InternalEntityEntry, string>)propertyAccessors.PreStoreGeneratedCurrentValueGetter)(entry));
Assert.Equal("ValueA", ((Func<InternalEntityEntry, string>)propertyAccessors.RelationshipSnapshotGetter)(entry));

var valueBuffer = new ValueBuffer(new object[] { 1, "ValueA" });
Assert.Equal("ValueA", ((Func<ValueBuffer, object>)propertyAccessors.ValueBufferGetter)(valueBuffer));
}

private class IndexedClass
{
private Dictionary<string, object> _internalValues = new Dictionary<string, object>()
{
{ "PropertyA", "ValueA" }
};

internal int Id { get; set; }

public object this[string name]
{
get => _internalValues[name];
}
}

private class NonIndexedClass
{
internal int Id { get; set; }
public string PropA { get; set; } = "ValueA";
}
}
}

0 comments on commit 514fda6

Please sign in to comment.