.net core System.NotSupportedException从NetCoreApp2.1调用OData服务时

.net core System.NotSupportedException从NetCoreApp2.1调用OData服务时,.net-core,odata,.net Core,Odata,我已经建立了一个多目标(net4.5.2/netstandard2)类库,允许使用我们的一个企业OData服务。 要访问此OData服务,我们使用 不幸的是,当尝试在Netcoreapp2.1应用程序中使用我的库时,我在尝试枚举集合时遇到了一个问题 Container.MyDataSet.ToList()生成以下异常: “System.NotSupportedException:此目标框架未启用 您需要直接枚举数据服务查询。这是因为 枚举自动向数据发送同步请求 由于此框架仅支持异步操作, 您必须

我已经建立了一个多目标(net4.5.2/netstandard2)类库,允许使用我们的一个企业OData服务。 要访问此OData服务,我们使用

不幸的是,当尝试在Netcoreapp2.1应用程序中使用我的库时,我在尝试枚举集合时遇到了一个问题

Container.MyDataSet.ToList()生成以下异常:

“System.NotSupportedException:此目标框架未启用 您需要直接枚举数据服务查询。这是因为 枚举自动向数据发送同步请求 由于此框架仅支持异步操作, 您必须调用BeginExecute和EndExecute方法来 获取支持枚举的查询结果。“

在.Net 4.5.2应用程序中使用相同的多目标库时,我不会遇到此问题

查看一下Microsoft.OData.Client v7.5.0源代码,这种行为似乎是通过对.Net核心案例的特定处理而设计的

我错过什么了吗

以下代码可防止此问题,但几乎不可用:

var query = (DataServiceQuery<MyData>)Container.MyDataSet;
var taskFactory = new TaskFactory<IEnumerable<MyData>>();
var t = taskFactory.FromAsync(query.BeginExecute(null, null), data => query.EndExecute(data));
t.ConfigureAwait(false);
IEnumerable<MyData> result = t.Result;
var query=(DataServiceQuery)Container.MyDataSet;
var taskFactory=new taskFactory();
var t=taskFactory.fromsync(query.BeginExecute(null,null),data=>query.EndExecute(data));
t、 配置等待(false);
IEnumerable result=t.result;

如何在不添加特定代码的情况下在.Net核心应用程序中使用OData IQueryable?

如错误消息中所述,平台仅支持异步抓取。即使使用了它,也可能需要多次枚举结果——每次执行
ToList()
FirstOrDefault()
或其他类似的
System.Generics.Collections
操作时,基本上都是获取集合的
枚举数并对其进行枚举

我采用了这个解决方案:在我从OData库中获取可枚举结果之后,我立即对它们进行枚举,并将它们放在我实例化的另一个可枚举容器中(
Dictionary

var resultsQuery = this.oDataClient.MyAwesomeResults
    .AddQueryOption("$filter", "Name eq 'MyAwesomeName'")
    .AddQueryOption("$top", "5")
    .AddQueryOption("$skip", "2");

IEnumerable<MyAwesomeResult> resultsRaw = await 
resultsQuery.ExecuteAsync();
var results = new Dictionary<string, MyAwesomeResult>();`

foreach (var resultRaw in resultsRaw)
{
    results.Add(resultRaw.Key, resultRaw);
}
var resultsQuery=this.oDataClient.MyAwesomeResults
.AddQueryOption(“$filter”,“Name eq'MyAwesomeName'”)
.AddQueryOption(“$top”,“5”)
.AddQueryOption(“$skip”,“2”);
IEnumerable resultsRaw=等待
resultsQuery.ExecuteAsync();
var results=newdictionary()`
foreach(resultsRaw中的var resultRaw)
{
results.Add(resultRaw.Key,resultRaw);
}
然后我使用我实例化的容器——我不再需要再次枚举
DataServiceQuery.ExecuteAsync

正如@PanagiotisKanavos
DataServiceQuery.ToString()
所说,将返回OData查询的uri。 基于此,我编写了自己的
IQueryable

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

using Microsoft.OData.Client;

public class ODataLinqQuery<T> : IOrderedQueryable<T>
{
    public IQueryProvider Provider { get; }

    private DataServiceQuery<T> DataServiceQuery { get; }

    public ODataLinqQuery(DataServiceQuery<T> dataServiceQuery, MyClient client, Type finalType)
    {
        this.DataServiceQuery = dataServiceQuery;
        this.Provider = new ODataLinqQueryProvider<T>(dataServiceQuery, client, finalType);
    }

    public IEnumerator<T> GetEnumerator()
    {
        return this.Provider.Execute<IEnumerable<T>>(this.Expression).GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.Provider.Execute<System.Collections.IEnumerable>(this.Expression).GetEnumerator();
    }

    public Expression Expression => this.DataServiceQuery.Expression;

    public Type ElementType => typeof(T);
}
其中,
Odata
类仅用于Odata结果的反序列化,
GetResult
“just”使用正确的身份验证头调用其底层
HttpClient
GetAsync
方法,等待并反序列化结果:

using System.Collections.Generic;

using Newtonsoft.Json;

public class OData<T> : OData where T : class
{
    public override IEnumerable<object> Objects => this.Value;

    public List<T> Value { get; set; }
}

public class OData
{
    [JsonProperty("@odata.context")]
    public string Metadata { get; set; }

    public virtual IEnumerable<object> Objects { get; set; }
}

然后我可以应用过滤器、orderby、top和skip,并像使用标准的
IQueryable
一样获得结果。我知道这个实现是不完整的,OData的
IQueryable
没有SQL的大多数
IQueryable
那么完整,但它达到了我需要的最低限度。

错误解释了问题所在。您试图将查询转换为列表,而不是结果。OData查询不是在调用
ToList()
时执行的EF查询。实际问题似乎是如何在.NET Core中异步进行OData调用,而不是如何使用
ToList()
,答案并不简单。说“一团糟”更合适。我可以在源代码中看到一个实际委托给
TaskFactory.fromsync
GetAllPagesAsync
git Turn
显示这是4年前的代码,以这种方式编写到target.NET4.0。可以安全地假设它也不使用HttpClient。您可以尝试其他生成器,或者将查询转换为URL,并使用
HttpClient.GetAsync
异步调用它
DataServiceQuery.ToString()将返回URI@PanagiotisKanavos我使用
ToList()
用一个简单的例子来说明这个问题。你是正确的;它使用和底层HttpWebRequest。我会更精确地回答我的问题,看看我能用Uri实现什么。谢谢。我知道我可以枚举结果,但是如果不可靠的数据源是数千或百万行呢?关键是我不能将其表示为“标准”
IQueryable
,我可以在其上透明地应用筛选器、排序、top和skip。您可以在发送OData请求之前使用
ExecuteAsync()
。我已经更新了答案来说明这一部分。
using System.Collections.Generic;

using Newtonsoft.Json;

public class OData<T> : OData where T : class
{
    public override IEnumerable<object> Objects => this.Value;

    public List<T> Value { get; set; }
}

public class OData
{
    [JsonProperty("@odata.context")]
    public string Metadata { get; set; }

    public virtual IEnumerable<object> Objects { get; set; }
}
var myQueryable = new ODataLinqQuery<MyData>(this.Container.MyDataSet, myclient, typeof(MyData));