Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement IListSource on LocalView and EntityQueryable to further direct data binding #9003

Merged
merged 1 commit into from
Jun 28, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion src/EFCore/ChangeTracking/LocalView.cs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -46,7 +47,7 @@ namespace Microsoft.EntityFrameworkCore.ChangeTracking
/// </para>
/// </summary>
/// <typeparam name="TEntity">The type of the entity in the local view.</typeparam>
public class LocalView<TEntity> : ICollection<TEntity>, INotifyCollectionChanged, INotifyPropertyChanged, INotifyPropertyChanging
public class LocalView<TEntity> : ICollection<TEntity>, INotifyCollectionChanged, INotifyPropertyChanged, INotifyPropertyChanging, IListSource
where TEntity : class
{
private ObservableBackedBindingList<TEntity> _bindingList;
Expand Down Expand Up @@ -443,5 +444,26 @@ private void OnCollectionChanged(NotifyCollectionChangedAction action, object it
/// <returns> The binding list. </returns>
public virtual BindingList<TEntity> ToBindingList()
=> _bindingList ?? (_bindingList = new ObservableBackedBindingList<TEntity>(ToObservableCollection()));

/// <summary>
/// <para>
/// This method is called by data binding frameworks when attempting to data bind
/// directly to a <see cref="LocalView{TEntity}" />.
/// </para>
/// <para>
/// This implementation always throws an exception as <see cref="LocalView{TEntity}" />
/// does not maintain an ordered list with indexes. Instead call <see cref="ToObservableCollection" />
/// for WPF binding, or <see cref="ToBindingList" /> for WinForms.
/// </para>
/// </summary>
/// <exception cref="NotSupportedException"> Always thrown. </exception>
/// <returns> Never returns, always throws an exception. </returns>
IList IListSource.GetList() => throw new NotSupportedException(CoreStrings.DataBindingWithIListSource);

/// <summary>
/// Gets a value indicating whether the collection is a collection of System.Collections.IList objects.
/// Always returns false.
/// </summary>
bool IListSource.ContainsListCollection => false;
}
}
29 changes: 28 additions & 1 deletion src/EFCore/Query/Internal/EntityQueryable`.cs
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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.
/// </summary>
public class EntityQueryable<TResult> : QueryableBase<TResult>, IAsyncEnumerable<TResult>, IDetachableContext
public class EntityQueryable<TResult> : QueryableBase<TResult>, IAsyncEnumerable<TResult>, IDetachableContext, IListSource
{
/// <summary>
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
Expand All @@ -35,10 +39,33 @@ public EntityQueryable([NotNull] IAsyncQueryProvider provider, [NotNull] Express
{
}

/// <summary>
/// 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.
/// </summary>
IAsyncEnumerator<TResult> IAsyncEnumerable<TResult>.GetEnumerator()
=> ((IAsyncQueryProvider)Provider).ExecuteAsync<TResult>(Expression).GetEnumerator();

/// <summary>
/// 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.
/// </summary>
IDetachableContext IDetachableContext.DetachContext()
=> new EntityQueryable<TResult>(NullAsyncQueryProvider.Instance);

/// <summary>
/// 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.
/// </summary>
IList IListSource.GetList()
{
throw new NotSupportedException(CoreStrings.DataBindingWithIListSource);
}

/// <summary>
/// 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.
/// </summary>
bool IListSource.ContainsListCollection => false;
}
}
20 changes: 20 additions & 0 deletions test/EFCore.Tests/DbSetTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<NotSupportedException>(() => ((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<NotSupportedException>(() => ((IListSource)context.Gus.Local).GetList()).Message);
}
}

private class Category
{
public int Id { get; set; }
Expand Down