Skip to content

Commit

Permalink
Query: Add indexed property support
Browse files Browse the repository at this point in the history
Part of #13610
Resolves #15799
  • Loading branch information
smitpatel committed Jan 1, 2020
1 parent ce6e1da commit f4c733f
Show file tree
Hide file tree
Showing 7 changed files with 61 additions and 13 deletions.
7 changes: 4 additions & 3 deletions src/EFCore/ChangeTracking/Internal/SnapshotFactoryFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,10 @@ protected virtual Expression CreateSnapshotExpression(
continue;
}

var memberAccess = (Expression)Expression.MakeMemberAccess(
entityVariable,
propertyBase.GetMemberInfo(forMaterialization: false, forSet: false));
var memberInfo = propertyBase.GetMemberInfo(forMaterialization: false, forSet: false);
var memberAccess = propertyBase.IsIndexerProperty()
? Expression.MakeIndex(entityVariable, (PropertyInfo)memberInfo, new[] { Expression.Constant(propertyBase.Name) })
: (Expression)Expression.MakeMemberAccess(entityVariable, memberInfo);

if (memberAccess.Type != propertyBase.ClrType)
{
Expand Down
2 changes: 1 addition & 1 deletion src/EFCore/Metadata/Internal/TypeBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ public virtual PropertyInfo FindIndexerPropertyInfo()

if (!_indexerPropertyInitialized)
{
var indexerPropertyInfo = GetRuntimeProperties().Values.FirstOrDefault(pi => pi.IsIndexerProperty());
var indexerPropertyInfo = GetRuntimeProperties().Values.FirstOrDefault(PropertyInfoExtensions.IsIndexerProperty);

Interlocked.CompareExchange(ref _indexerPropertyInfo, indexerPropertyInfo, null);
_indexerPropertyInitialized = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -277,9 +277,8 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp
?? methodCallExpression.Update(null, new[] { Unwrap(newLeft), Unwrap(newRight) });
}

// Navigation via EF.Property() or via an indexer property
if (methodCallExpression.TryGetEFPropertyArguments(out _, out var propertyName)
|| methodCallExpression.TryGetEFIndexerArguments(out _, out propertyName))
// Navigation via EF.Property()
if (methodCallExpression.TryGetEFPropertyArguments(out _, out var propertyName))
{
newSource = Visit(arguments[0]);
var newMethodCall = methodCallExpression.Update(null, new[] { Unwrap(newSource), arguments[1] });
Expand All @@ -288,6 +287,16 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp
: newMethodCall;
}

// Navigation via an indexer property
if (methodCallExpression.TryGetEFIndexerArguments(out _, out propertyName))
{
newSource = Visit(methodCallExpression.Object);
var newMethodCall = methodCallExpression.Update(Unwrap(newSource), new[] { arguments[0] });
return newSource is EntityReferenceExpression entityWrapper
? entityWrapper.TraverseProperty(propertyName, newMethodCall)
: newMethodCall;
}

switch (method.Name)
{
// These are methods that require special handling
Expand Down Expand Up @@ -1071,7 +1080,8 @@ protected struct EntityOrDtoType
public static EntityOrDtoType FromEntityReferenceExpression(EntityReferenceExpression ere)
=> new EntityOrDtoType
{
EntityType = ere.IsEntityType ? ere.EntityType : null, DtoType = ere.IsDtoType ? ere.DtoType : null
EntityType = ere.IsEntityType ? ere.EntityType : null,
DtoType = ere.IsDtoType ? ere.DtoType : null
};

public static EntityOrDtoType FromDtoType(Dictionary<string, EntityOrDtoType> dtoType)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,12 @@ protected virtual QueryAsserter<GearsOfWarContext> CreateQueryAsserter(

protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context)
{
modelBuilder.Entity<City>().HasKey(c => c.Name);
modelBuilder.Entity<City>(
b =>
{
b.HasKey(c => c.Name);
b.Metadata.AddIndexedProperty("Nation", typeof(string));
});

modelBuilder.Entity<Gear>(
b =>
Expand Down
11 changes: 10 additions & 1 deletion test/EFCore.Specification.Tests/Query/GearsOfWarQueryTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7397,7 +7397,7 @@ public virtual Task OrderBy_bool_coming_from_optional_navigation(bool async)
ss => ss.Set<Weapon>().Select(w => w.SynergyWith).OrderBy(g => MaybeScalar<bool>(g, () => g.IsAutomatic)),
assertOrder: true);
}

[ConditionalFact]
public virtual void Byte_array_filter_by_length_parameter_compiled()
{
Expand All @@ -7411,6 +7411,15 @@ public virtual void Byte_array_filter_by_length_parameter_compiled()
Assert.Equal(2, query(context, byteQueryParam));
}

[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
public virtual Task Can_query_on_indexed_properties(bool async)
{
return AssertQuery(
async,
ss => ss.Set<City>().Where(c => (string)c["Nation"] == "Tyrus"));
}

protected GearsOfWarContext CreateContext() => Fixture.CreateContext();

protected virtual void ClearLog()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,41 @@
// 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;

namespace Microsoft.EntityFrameworkCore.TestModels.GearsOfWarModel
{
public class City
{
private string _nation;
// non-integer key with not conventional name
public string Name { get; set; }

public string Location { get; set; }

public string Nation { get; set; }
public object this[string name]
{
get
{
if (!string.Equals(name, "Nation", StringComparison.Ordinal))
{
throw new InvalidOperationException($"Indexed property with key {name} is not defined on {nameof(City)}.");
}

return _nation;
}

set
{
if (!string.Equals(name, "Nation", StringComparison.Ordinal))
{
throw new InvalidOperationException($"Indexed property with key {name} is not defined on {nameof(City)}.");
}

_nation = (string)value;
}
}

public List<Gear> BornGears { get; set; }
public List<Gear> StationedGears { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,15 +151,15 @@ public static IReadOnlyList<City> CreateCities()
{
Location = "Jacinto's location",
Name = "Jacinto",
Nation = "Tyrus"
};
jacinto["Nation"] = "Tyrus";

var ephyra = new City
{
Location = "Ephyra's location",
Name = "Ephyra",
Nation = "Tyrus"
};
ephyra["Nation"] = "Tyrus";

var hanover = new City { Location = "Hanover's location", Name = "Hanover" };

Expand Down

0 comments on commit f4c733f

Please sign in to comment.