diff --git a/src/EFCore/ChangeTracking/LocalView.cs b/src/EFCore/ChangeTracking/LocalView.cs index 30ed6916834..baf3e6afd8c 100644 --- a/src/EFCore/ChangeTracking/LocalView.cs +++ b/src/EFCore/ChangeTracking/LocalView.cs @@ -1,6 +1,7 @@ // 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; using System.Collections.Generic; using System.Collections.ObjectModel; @@ -46,7 +47,7 @@ namespace Microsoft.EntityFrameworkCore.ChangeTracking /// /// /// The type of the entity in the local view. - public class LocalView : ICollection, INotifyCollectionChanged, INotifyPropertyChanged, INotifyPropertyChanging + public class LocalView : ICollection, INotifyCollectionChanged, INotifyPropertyChanged, INotifyPropertyChanging, IListSource where TEntity : class { private ObservableBackedBindingList _bindingList; @@ -443,5 +444,26 @@ private void OnCollectionChanged(NotifyCollectionChangedAction action, object it /// The binding list. public virtual BindingList ToBindingList() => _bindingList ?? (_bindingList = new ObservableBackedBindingList(ToObservableCollection())); + + /// + /// + /// This method is called by data binding frameworks when attempting to data bind + /// directly to a . + /// + /// + /// This implementation always throws an exception as + /// does not maintain an ordered list with indexes. Instead call + /// for WPF binding, or for WinForms. + /// + /// + /// Always thrown. + /// Never returns, always throws an exception. + IList IListSource.GetList() => throw new NotSupportedException(CoreStrings.DataBindingWithIListSource); + + /// + /// Gets a value indicating whether the collection is a collection of System.Collections.IList objects. + /// Always returns false. + /// + bool IListSource.ContainsListCollection => false; } } diff --git a/src/EFCore/Query/Internal/EntityQueryable`.cs b/src/EFCore/Query/Internal/EntityQueryable`.cs index b43033e2a0c..cc7db187b61 100644 --- a/src/EFCore/Query/Internal/EntityQueryable`.cs +++ b/src/EFCore/Query/Internal/EntityQueryable`.cs @@ -1,10 +1,14 @@ // 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; using System.Collections.Generic; +using System.ComponentModel; using System.Linq.Expressions; using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Utilities; +using Microsoft.EntityFrameworkCore.Internal; using Remotion.Linq; namespace Microsoft.EntityFrameworkCore.Query.Internal @@ -13,7 +17,7 @@ namespace Microsoft.EntityFrameworkCore.Query.Internal /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. /// - public class EntityQueryable : QueryableBase, IAsyncEnumerable, IDetachableContext + public class EntityQueryable : QueryableBase, IAsyncEnumerable, IDetachableContext, IListSource { /// /// This API supports the Entity Framework Core infrastructure and is not intended to be used @@ -35,10 +39,33 @@ public EntityQueryable([NotNull] IAsyncQueryProvider provider, [NotNull] Express { } + /// + /// This API supports the Entity Framework Core infrastructure and is not intended to be used + /// directly from your code. This API may change or be removed in future releases. + /// IAsyncEnumerator IAsyncEnumerable.GetEnumerator() => ((IAsyncQueryProvider)Provider).ExecuteAsync(Expression).GetEnumerator(); + /// + /// This API supports the Entity Framework Core infrastructure and is not intended to be used + /// directly from your code. This API may change or be removed in future releases. + /// IDetachableContext IDetachableContext.DetachContext() => new EntityQueryable(NullAsyncQueryProvider.Instance); + + /// + /// This API supports the Entity Framework Core infrastructure and is not intended to be used + /// directly from your code. This API may change or be removed in future releases. + /// + IList IListSource.GetList() + { + throw new NotSupportedException(CoreStrings.DataBindingWithIListSource); + } + + /// + /// This API supports the Entity Framework Core infrastructure and is not intended to be used + /// directly from your code. This API may change or be removed in future releases. + /// + bool IListSource.ContainsListCollection => false; } } diff --git a/test/EFCore.Tests/DbSetTest.cs b/test/EFCore.Tests/DbSetTest.cs index 8610c889e64..2cb7f4e311f 100644 --- a/test/EFCore.Tests/DbSetTest.cs +++ b/test/EFCore.Tests/DbSetTest.cs @@ -566,6 +566,26 @@ public void Throws_when_using_with_IListSource() } } + [Fact] + public void Throws_when_using_query_with_IListSource() + { + using (var context = new EarlyLearningCenter()) + { + Assert.Equal(CoreStrings.DataBindingWithIListSource, + Assert.Throws(() => ((IListSource)context.Gus.Distinct()).GetList()).Message); + } + } + + [Fact] + public void Throws_when_using_Local_with_IListSource() + { + using (var context = new EarlyLearningCenter()) + { + Assert.Equal(CoreStrings.DataBindingWithIListSource, + Assert.Throws(() => ((IListSource)context.Gus.Local).GetList()).Message); + } + } + private class Category { public int Id { get; set; }