【问题标题】:C# Insertion Order into List from Entity Framework实体框架中的 C# 插入顺序到列表中
【发布时间】:2017-06-14 02:29:33
【问题描述】:

当我从 Entity Framework Select 实例化 C# 列表时,我很惊讶地发现我在 C# 列表中遇到了插入顺序问题。

我正在创建多个包含 List<int> 键的 dto,但每个 dto 对象的插入顺序是随机的。这是最奇怪的事情。我认为 C# 列表中的插入顺序被保留了,所以我试图找出确定顺序的位置。

服务器代码:

var locations = Context.Location
        .Where(x => x.fk_LocationId == id)
        .Include(t => t.DoctorLocations);

Region.Locations = locations
        .SelectMany(x => x.DoctorLocations)
        .Where(y => y.fk_LocationId == id)
        .Select(x =>
            new SortableItem
            {
                Keys = new List<int> { x.fk_doctorId, x.fk_locationId },
                Type = "Practice",
                Priority = x.Priority ?? 0,
            })
        .OrderBy(x => x.Priority)
        .ToList();

查看:

@for (var i = 0; i < Model.DoctorLocations.Count(); i++)
{
    @Html.ActionLink("Remove", "Delete", "DoctorLocation" new { doctorId= Model.Locations[i].Keys[0], locationId= Model.Locations[i].Keys[1], }, null)
}

根据@PaulAbbot 更新

我删除了SelectMany,但得到了相同的结果。我还创建了更多 dto 对象以在它们交替时寻找模式。我没有看到,但它们在从服务器返回的方式上是一致的。

Region.Locations = Context.DoctorLocations
        .Where(y => (y.fk_doctorId == doctorId) &&
            locations.Select(x => x.locationId).Contains(y.fk_locationId))
        .Where(y => y.fk_doctorId == doctorid)
        .Select(x =>
            new SortableItem {
                Keys = new List<int> { x.fk_doctorId, x.fk_locationId }
            })
        .OrderBy(x => x.Priority)
        .ToList();

【问题讨论】:

  • 真的是随机的吗?看起来您的 SelectMany 可能会丢东西,因此它按每个位置的优先级进行子排序,而不是按全局优先级排序。你得到的是 1-2-3-1-2-3 而不是 1-1-2-2-3-3?
  • 很难说,Keys = new List { x.fk_doctorId, x.fk_locationId } 将在以医生为第一个 id 和以位置为第一个 id 之间交替。我认为您对 selectman 的看法是正确的。我会看看我是否可以删除它并找到另一种测试方法。
  • 查询看起来没问题。生成的 SQL 是什么?
  • 这是个好问题。让我检查一下。
  • 嗯,你的意思是Keys列表中元素的顺序吗?看起来 EF 处理这种类型的投影时存在错误。我刚刚尝试过类似的东西,但 SQL 完全是错误的(最新的 EF6.1.3)

标签: c# asp.net asp.net-mvc entity-framework


【解决方案1】:

在 EF6 处理包含 new List&lt;int&gt; { val1, val2, ...} 之类的构造的投影中似乎存在错误。虽然它不会生成NotSupportedException,但正确实现结果所需的生成的 SQL ORDER BY 子句是错误的(使用常量而不是索引选择器表达式)。

如果您不需要 IQueryable&lt;T&gt; 结果,我会建议通常的 双投影 解决方法 - 在 LINQ to Entities 查询中使用普通匿名类型投影,然后在最后切换到 LINQ 到对象并进行所需的投影:

var result = locations
    .SelectMany(x => x.DoctorLocations)
    .Where(y => y.fk_LocationId == id)
    .Select(x => new
    {
        K1 = x.fk_doctorId, K2 = x.fk_locationId,
        Type = "Practice",
        Priority = x.Priority ?? 0,
    })
    .OrderBy(x => x.Priority)
    .AsEnumerable() // switch to L2O
    .Select(x => new SortableItem
    {
        Keys = new List<int> { x.K1, x.K2 },
        Type = x.Type,
        Priority = x.Priority,
    })
    .ToList();

我知道,烦人,但至少可以按预期工作:)

【讨论】:

  • 成功了。谢谢,感谢您解释为什么它解决了这个问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-08-20
  • 1970-01-01
  • 2021-10-12
  • 1970-01-01
  • 2012-06-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多