4

我有一个gridview,它的数据源是以下函数:

public static List<Train> GetTrainsByIDs(int [] ids) {
    using (var context = new MyEntities()) 
    {
        return ids.Select(x => context.Trains.Single(y => y.TrainID ==x)).AsQueryable().Include(x=>x.Station).ToList();
    }
}

网格视图的 ItemTemplate 为<%# Eval("Station.Name") %>. The ObjectContext instance has been disposed and can no longer be used for operations that require a connection尽管我使用了 include 方法,但这会导致错误。

当我将功能更改为

public static List<Train> GetTrainsByIDs(int [] ids) {
    using (var context = new MyEntities()) 
    {
        return context.Trains.Where(x => ids.Contains(x.TrainID)).Include(x=>x.Station).ToList();
    }
}

它工作正常,但是它们以错误的顺序出现,而且如果我有 2 个相同的 id,我希望列表中有 2 个相同的火车。

除了创建一个新的视图模型,我还能做些什么吗?感谢您的任何帮助

4

2 回答 2

1

至于第一个查询:那是延迟执行。你创建了一个IEnumerableof Train,注意到它没有Include方法,所以将它转换为IQueryable,添加 Include 并添加ToList()以防止延迟加载。

但根据DbExtensions.Include 上的 MSDN

此扩展方法调用 IQueryable 源对象的 Include(String) 方法(如果存在此类方法)。如果源 IQueryable 没有匹配方法,则此方法不执行任何操作。

(强调我的)

select 的结果是一个IEnumerable转换为IQueryable,但现在由EnumerableQuerywhich 不实现Include。什么也没有发生。

现在数据进入试图显示车站的网格,这会在上下文消失时触发延迟加载。

除此之外,这种设计还有另一个缺陷:它分别为每个 id 触发一个查询。

所以第二个查询要好得多。这是一个查询,包括Stations。但是现在顺序是由数据库返回的顺序决定的。你可以Concat用来解决这个问题:

IQueryable<Train> qbase = context.Trains.Include(x=>x.Station);
IQueryable<Train> q = null;

foreach (var id in ids)
{
  var id1 = id; // Prevent modified closure.
  if (q == null)
    q = qbase.Where(t => t.Id == id1);
  else
    q = q.Concat(qbase.Where (t => t.Id == id1));
}

生成的查询不是很优雅(至少可以说),但毕竟它是一个查询而不是多个查询。

于 2012-09-02T21:55:03.063 回答
0

在阅读了@Gert Arnold 的答案并获得了分两个阶段执行此操作的想法后,我非常简单地使用了这样的第一个查询:

using (context = new MyEntities())
{
    var trns = context.Trains.Include(x => x.Station);
    return ids.Select(x => trns.Single(y => y.TrainID == x)).ToList();
}
于 2012-09-05T18:10:42.507 回答