diff --git a/src/EFCore/Metadata/Conventions/BackingFieldConvention.cs b/src/EFCore/Metadata/Conventions/BackingFieldConvention.cs
index 72f29808dd5..7afd542d55b 100644
--- a/src/EFCore/Metadata/Conventions/BackingFieldConvention.cs
+++ b/src/EFCore/Metadata/Conventions/BackingFieldConvention.cs
@@ -84,7 +84,8 @@ public virtual void ProcessNavigationAdded(
private FieldInfo GetFieldToSet(IConventionPropertyBase propertyBase)
{
if (propertyBase == null
- || !ConfigurationSource.Convention.Overrides(propertyBase.GetFieldInfoConfigurationSource()))
+ || !ConfigurationSource.Convention.Overrides(propertyBase.GetFieldInfoConfigurationSource())
+ || propertyBase.IsIndexerProperty())
{
return null;
}
diff --git a/src/EFCore/Metadata/Internal/PropertyBase.cs b/src/EFCore/Metadata/Internal/PropertyBase.cs
index 3a3f6f6b789..4c96274ac7b 100644
--- a/src/EFCore/Metadata/Internal/PropertyBase.cs
+++ b/src/EFCore/Metadata/Internal/PropertyBase.cs
@@ -151,6 +151,13 @@ public virtual void SetField([CanBeNull] FieldInfo fieldInfo, ConfigurationSourc
if (fieldInfo != null)
{
IsCompatible(fieldInfo, ClrType, DeclaringType.ClrType, Name, shouldThrow: true);
+
+ if (PropertyInfo != null
+ && PropertyInfo.IsIndexerProperty())
+ {
+ throw new InvalidOperationException(
+ CoreStrings.BackingFieldOnIndexer(fieldInfo.GetSimpleMemberName(), DeclaringType.DisplayName(), Name));
+ }
}
if (PropertyInfo == null
diff --git a/src/EFCore/Properties/CoreStrings.Designer.cs b/src/EFCore/Properties/CoreStrings.Designer.cs
index 25169f966c4..28e9e671be8 100644
--- a/src/EFCore/Properties/CoreStrings.Designer.cs
+++ b/src/EFCore/Properties/CoreStrings.Designer.cs
@@ -2316,6 +2316,14 @@ public static string NonIndexerEntityType([CanBeNull] object property, [CanBeNul
GetString("NonIndexerEntityType", nameof(property), nameof(entity), nameof(type)),
property, entity, type);
+ ///
+ /// Cannot set backing field '{field}' for the indexer property '{entityType}.{property}'. Indexer properties are not allowed to use a backing field.
+ ///
+ public static string BackingFieldOnIndexer([CanBeNull] object field, [CanBeNull] object entityType, [CanBeNull] object property)
+ => string.Format(
+ GetString("BackingFieldOnIndexer", nameof(field), nameof(entityType), nameof(property)),
+ field, entityType, property);
+
private static string GetString(string name, params string[] formatterNames)
{
var value = _resourceManager.GetString(name);
diff --git a/src/EFCore/Properties/CoreStrings.resx b/src/EFCore/Properties/CoreStrings.resx
index 54d2bba2744..724a621090a 100644
--- a/src/EFCore/Properties/CoreStrings.resx
+++ b/src/EFCore/Properties/CoreStrings.resx
@@ -1248,4 +1248,7 @@
Cannot add property '{property}' on entity type '{entity}' since there is no indexer on '{entity}' taking a single argument of type '{type}'.
+
+ Cannot set backing field '{field}' for the indexer property '{entityType}.{property}'. Indexer properties are not allowed to use a backing field.
+
\ No newline at end of file
diff --git a/test/EFCore.Tests/Metadata/Conventions/BackingFieldConventionTest.cs b/test/EFCore.Tests/Metadata/Conventions/BackingFieldConventionTest.cs
index 87e1c52a244..c0120968760 100644
--- a/test/EFCore.Tests/Metadata/Conventions/BackingFieldConventionTest.cs
+++ b/test/EFCore.Tests/Metadata/Conventions/BackingFieldConventionTest.cs
@@ -241,6 +241,29 @@ public void FieldInfo_set_by_annotation_is_used()
Assert.Equal("m_onTheRun", property.GetFieldName());
}
+ [ConditionalFact]
+ public void Backing_field_is_not_discovered_for_indexer_property()
+ {
+ var entityType = CreateModel().AddEntityType(typeof(IndexedClass));
+ var property = entityType.AddIndexedProperty("Nation", typeof(string));
+
+ RunConvention(property);
+ Validate(property);
+
+ Assert.Null(property.GetFieldName());
+ }
+
+ [ConditionalFact]
+ public void Setting_field_on_indexer_property_throws()
+ {
+ var entityType = CreateModel().AddEntityType(typeof(IndexedClass));
+ var property = entityType.AddIndexedProperty("Nation", typeof(string));
+
+ Assert.Equal(
+ CoreStrings.BackingFieldOnIndexer("nation", entityType.DisplayName(), "Nation"),
+ Assert.Throws(() => property.SetField("nation")).Message);
+ }
+
private void RunConvention(IMutableProperty property)
=> new BackingFieldConvention(CreateDependencies())
.ProcessPropertyAdded(
@@ -459,6 +482,17 @@ public object OnTheRun
}
}
+ private class IndexedClass
+ {
+ private string nation;
+ private string _nation;
+ private string _Nation;
+ private string m_nation;
+ private string m_Nation;
+
+ public object this[string name] => null;
+ }
+
#pragma warning disable RCS1222 // Merge preprocessor directives.
#pragma warning restore 649, 169
#pragma warning restore IDE0027 // Use expression body for accessors