我想知道DataServiceContext
类的正确用法是什么。
我是否应该为每个工作单元和/或范围创建一个新实例,例如:
public SomeEntity GetSomeEntities()
{
DataServiceContext context = new DataServiceContext(...);
DataServiceQuery<SomeEntity> query = context.SomeEntity
.Where(x => x.SomeProperty == someValue);
IEnumerable<SomeEntity> someEntities = await Task.Factory.FromAsync(
query.BeginExecute, query.EndExecute, null);
return someEntities.ToList();
}
还是应该使用共享实例:
private readonly DataServiceContext context = new DataServiceContext(...);
public SomeEntity GetSomeEntities()
{
DataServiceQuery<SomeEntity> query = context.SomeEntity
.Where(x => x.SomeProperty == someValue);
IEnumerable<SomeEntity> someEntities = await Task.Factory.FromAsync(
query.BeginExecute, query.EndExecute, null);
return someEntities.ToList();
}
我了解在使用EntityFramework上下文的情况下,您可以使用第一种方法,但是我不确定OData的情况-特别是是否始终在重新创建Context时不会像重新创建那样导致套接字耗尽HttpClient
就可以了。
一个与上下文有关的线程安全性相关问题-从多个并发线程中使用相同的上下文是否安全,如下所示:
DataServiceContext context = new DataServiceContext(...);
List<Task<IEnumerable<SomeEntity>>> downloadTasks = new List<Task<IEnumerable<SomeEntity>>>();
using (CancellationTokenSource cancellationTokenSource = new CancellationTokenSource())
{
foreach (var batch in someEntitiesList.Batch(_defaultBatchSize))
{
if (cancellationTokenSource.IsCancellationRequested)
break;
string filter = string.Join(" or ", batch.Select(i => $"(Id eq '{i.Id}')"));
Task<IEnumerable<SomeEntity>> task = Task.Run(() =>
{
try
{
DataServiceQuery<SomeEntity> query = context.SomeEntity
.AddQueryOption("$filter", filter)
.OrderBy(x => x.Id)
as DataServiceQuery<SomeEntity>;
IEnumerable<SomeEntity> someEntities = query.Execute();
return someEntities;
}
catch(Exception)
{
cancellationTokenSource.Cancel();
throw;
}
}, cancellationTokenSource.Token);
downloadTasks.Add(task);
}
await Task.WhenAll(downloadTasks);
//do something with results
}
还是我需要针对每个任务使用新的上下文?
List<Task<IEnumerable<SomeEntity>>> downloadTasks = new List<Task<IEnumerable<SomeEntity>>>();
using (CancellationTokenSource cancellationTokenSource = new CancellationTokenSource())
{
foreach (var batch in someEntitiesList.Batch(_defaultBatchSize))
{
if (cancellationTokenSource.IsCancellationRequested)
break;
string filter = string.Join(" or ", batch.Select(i => $"(Id eq '{i.Id}')"));
Task<IEnumerable<SomeEntity>> task = Task.Run(() =>
{
try
{
DataServiceContext context = new DataServiceContext(...);
DataServiceQuery<SomeEntity> query = context.SomeEntity
.AddQueryOption("$filter", filter)
.OrderBy(x => x.Id)
as DataServiceQuery<SomeEntity>;
IEnumerable<SomeEntity> someEntities = query.Execute();
return someEntities;
}
catch(Exception)
{
cancellationTokenSource.Cancel();
throw;
}
}, cancellationTokenSource.Token);
downloadTasks.Add(task);
}
await Task.WhenAll(downloadTasks);
//do something with results
}