【问题标题】:Perform a select and expand in the same query with breeze is not supported不支持在同一个查询中使用微风执行选择和展开
【发布时间】:2015-08-05 21:42:10
【问题描述】:

我使用 Durandal/breeze 开发了一个 asp.net 解决方案。

这是获取所有托运人的代码:

var query = EntityQuery.from('Shippers')
               .select('id, name, street, city');

return manager.executeQuery(query)
        .then(querySucceeded)
        .fail(queryFailed);

这里是相关模型:

public class Shipper
{
    [Key]
    public int Id { get; set; }
    public string Name { get; set; }
    public string Street { get; set; }
    public string Number { get; set; }
    public City City { get; set; }
}

public class City
{
    public int Id { get; set; }        
    public string Name { get; set; }
    public string PostCode { get; set; }
    public Country Country { get; set; }
}

现在我还需要包括国家/地区

public class Country
{
    [Key]
    public int Id { get; set; }
    public string Code { get; set; }
    public string Name { get; set; }
}

但是对于实际查询,我没有得到国家/地区。

我试试:

var query = EntityQuery.from('Shippers')
               .select('id, name, street, city')
               .expand('City.Country');

但我得到了错误:

use of both 'expand' and 'select' in the same query is not currently supported

我的问题:如何获取国家/地区?


更新

按照杰的建议,我们可以这样做:

var query = EntityQuery.from('Shippers')
       .select('id, name, street, city, city.country')

现在,我得到了一个city_Country 对象:

我不明白为什么我们得到这个city_Country,因为城市\国家对象中已经有国家数据:

此外,它给我带来了问题,因为我的下一条语句尝试将我的 dto 映射到我的实体中,而我的实体中不存在这个 city_Country 对象,并且映射时发生错误。

下面我们看到我的实体对象并没有city_Country对象:

我必须对我的映射做一些特殊的事情来避免它吗?

下面是我的映射操作函数:

function mapToEntity(entity, dto) {
     // entity is an object with observables
     // dto is from json
     for (var prop in dto) {
          if (dto.hasOwnProperty(prop)) {
             entity[prop](dto[prop]);
          }
     }
     return entity;
}

【问题讨论】:

    标签: breeze durandal


    【解决方案1】:

    我不确定使用投影来“部分”填充实体是一种好习惯,这就是您正在做的事情。 Breeze 将自动映射它在您的结果集中找到的任何真正的“实体”。那么为什么不简单地使用

    var query = EntityQuery.from('Shippers')
        .where(...)
        .expand('city.country');
    

    即时结果将是托运人的集合,但每个托运人的城市和嵌套国家属性也将完全解析为实体。它们可以通过返回的 shippers 导航获得,但如果您想直接查询它们,它们也可以在 entityManager 缓存中使用。

    第二个注意事项:Breeze“扩展”语义具有与实体框架相同的限制。这意味着我们不能扩展投影的属性。

    所以你可以跳过投影(如上)

    var query = EntityQuery.from('Shippers')
       .where(...)
       .expand('city.country')
    

    并获得完整的“托运人”实体,城市上的“城市”和“国家”属性都被填充。...或者你可以做一个投影,在这种情况下你自己执行扩展的等价物。即

    在这种情况下,你会

    var query = EntityQuery.from('Shippers')
      .select('id, name, street, city, city.country')
    

    在这种情况下,结果集中的每个项目都将包含 5 个属性。请注意,在这种情况下,只有“city”和“city.country”属性将被添加到 entityManager 的缓存中,因为它们是结果集中唯一的“真实”实体。即没有托运人的

    要明确的是,查询的“结果”和查询的“副作用”是不同的。查询的顶级结果将完全符合您的预期。查询的“副作用”是您执行的任何“扩展”的结果。这些不会改变查询的形状,它们只是改变结果中任何嵌套“实体”属性的分辨率。

    希望这会有所帮助。

    【讨论】:

    • 感谢您的解释。为什么我在查询中使用投影是因为某些实体可能包含很多“重”属性,例如图像,......所以在查询简单列表的情况下,最好只获取必要的属性或实体的所有属性?
    • 一种选择是简单地将“重”属性映射到它们自己的实体类型,并与将排除它们的“父类型”一一对应。另一种是实际测量使用“完整”实体的性能/内存占用量,看看它们是否像您怀疑的那样昂贵。我将从最简单的架构开始,并且只有在您向自己证明它是非性能时才将其复杂化/优化。即不要过早优化。
    【解决方案2】:

    我们确实允许这样做:

    var query = EntityQuery.from('Shippers')
               .select('id, name, street, city, city.country')
    

    【讨论】:

    • 我更新了我的问题以显示结果。你能看看吗?谢谢。
    • 对一对多属性执行此操作不起作用 ExceptionMessage:“无法在类型 'System.Collections.Generic.ICollection`1[Domain.Entities.UserProfile] 上找到属性 'UserName' ]'。",
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-23
    • 1970-01-01
    • 2022-01-18
    • 2019-02-06
    • 1970-01-01
    相关资源
    最近更新 更多