【问题标题】:How can I retrieve a calculated property without expanding to related navigation properties?如何在不扩展到相关导航属性的情况下检索计算属性?
【发布时间】:2020-04-21 06:48:39
【问题描述】:

我遵循了这里的好建议 (Handling calculated properties with breezejs and web api) 以允许 Breeze 访问我在服务器端的部分类中设置的计算属性:

    public partial class EventPerson
{
    [NotMapped]
    public Decimal TotalAmountPaid
    {
        get
        {
            return this.EventPersonPayments.Sum(p => p.AmtPaid);
        }
    }
}

但是对于我检索的每个 EventPerson,此值显示为 0,除非我使用 .expand("EventPersonPayments") 客户端或 .Include("EventPersonPayments") 服务器端。

我不希望 EventPersonPayments 中的所有数据都被序列化并发送到客户端;我想要的只是总和值。这可能吗?

编辑:如果我的计算属性是从实体中已有的其他属性派生的,那么它可以正常工作。例如:

    public partial class EventPerson
{
    [NotMapped]
    public String DisplayName
    {
        get
        {
            return this.FirstName + " " + this.LastName;
        }
    }
}

返回 JSON 有效负载中的 DisplayName。除非我专门加载所有额外信息,否则前一种类型的计算属性总是返回 0 或 null。

我考虑将这些转换为 SQL Server 中的用户定义函数,但我不应该仅仅为了让它按应有的方式工作而丢弃我的 C# 代码。

【问题讨论】:

  • 如果我不需要为了得到我需要的计算值而积极地把所有东西都带过来,那么我刚刚做了一个计算,我的 JSON 有效负载将是大小的 1/5。有人有什么想法吗?
  • 我有点惊讶其他人似乎也没有这个问题;我知道求和是 Breeze JS 应该为将来的版本所做的事情,但即使他们这样做了,基于导航属性的计算属性仍然是一项重要的功能。其他人是否以不同的方式处理这个问题?

标签: c# breeze


【解决方案1】:

一种方法是使用包含被查询实体和一些计算属性的投影。即您的服务器查询可能如下所示:

[HttpGet]
public IQueryable<Object> CustomersAndFreightTotals(companyName) {
  var stuff = ContextProvider.Context.Customers
    .Where(c => c.CompanyName.StartsWith(companyName))
    .Select(c => new { Customer = c, FreightTotal = c.Orders.Sum(o => o.Freight)) });
  return stuff;
}

此查询将加载以指定公司名称开头的所有客户,但还会为您提供每个客户的所有订单的“总运费”。

你可以用类似这样的代码来调用它:

var query = EntityQuery.from("CustomersAndFreightTotals")
    .withParameters({ companyName: "C" });
myEntityManager.executeQuery(query).then(function(data) {
  var results = data.results;
  results.forEach(function (r) {
    // note that each customer WILL also be added to the local entityManager
    // because it is an entity, whereas the freightTotal is only available here.
    var customer = r.Customer;  
    var freightTotal = r.FreightTotal;
    // and if you wanted to hack the customer entity
    // you could do this.
    customer.freightTotal = freightTotal;
  });
}

【讨论】:

  • 然后将“客户”排除在投影之外,或者只包含您感兴趣的客户属性。即 .Select( CompanyName = c.CompanyName, FreightTotal = ... )
  • 这确实有效,但也不是没有问题。我需要将我的所有逻辑从我的所有部分类移到查询本身;如果它在查询中,我不能在其他服务器端代码中使用它。此外,我不能在 Breeze 中对返回 Object 的方法进行 .expand()。
【解决方案2】:

我也遇到了这个问题,还有几个其他问题/答案似乎指向正在发生的事情:

据我了解,简而言之,[NotMapped] 会阻止 Breeze/Entity Framework 正确连接到现场。然而,Json.NET 将序列化该字段并将其发送到 Breeze,如果您通过类的构造函数手动设置它,它将填充该字段,并且已通过对 Entity Framework 识别的其他属性使用 expand 检索数据。这似乎几乎是一个意外,在这种情况下,您可以让 [NotMapped] 字段在客户端上工作; Breeze+Entity Framework 似乎不是为这种情况设计的。

您可以对suggestion at Breeze's User Voice 进行投票和评论。如果没有实体框架团队的一些工作,我不确定 Breeze 是否可以自己解决这个问题,但至少它可以让他们注意到这个问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-12-06
    • 2015-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-30
    • 2020-11-24
    相关资源
    最近更新 更多