我在Durandal网络应用程序中使用breezejs。
这是我的代码,以获取我的发票和&背后的界限:
var getInvoiceById = function (invoiceId, invoiceObservable, forceRemote) {
// Input: invoiceId: the id of the invoice to retrieve
// Input: forceRemote: boolean to force the fetch from server
// Output: invoiceObservable: an observable filled with the invoice
if (forceRemote)
queryCacheInvoice = {};
var query = entityQuery.from('Invoices')
.where('id', '==', invoiceId)
.expand("Client, Client.Contacts, Lines")
.orderBy('Lines.Number');
var isInCache = queryCacheInvoice[invoiceId];
if (isInCache && !forceRemote) {
query = query.using(breeze.FetchStrategy.FromLocalCache);
} else {
queryCacheInvoice[invoiceId] = true;
query = query.using(breeze.FetchStrategy.FromServer);
}
return manager.executeQuery(query)
.then(querySucceeded)
.fail(queryFailed);
function querySucceeded(data) {
invoiceObservable(data.results[0]);
}
};
以下是Invoice的模型:
public class Invoice
{
[Key]
public int Id { get; set; }
public string Number { get; set; }
public DateTime? Date { get; set; }
public int? ClientId { get; set; }
public string Comment { get; set; }
public double? TotalExclVAT { get; set; }
public double? TotalInclVAT { get; set; }
public double? TotalVAT { get; set; }
public bool? WithoutVAT { get; set; }
public virtual List<InvoiceLine> Lines { get; set; }
public virtual Client Client { get; set; }
}
请注意,对于每张发票,我有很多发票行:
public virtual List<InvoiceLine> Lines { get; set; }
以下是InvoiceLine的模型:
public class InvoiceLine
{
[Key]
public int Id { get; set; }
[Required]
public int Number { get; set; }
[Required]
public string Description { get; set; }
public int InvoiceId { get; set; }
public Invoice Invoice { get; set; }
}
问题:当我执行此微风查询时,我收到以下错误:
检索数据时出错。无法找到属性:类型上的行:发票
问题在于orderBy子句。我在Invoice和InvoiceLine之间有一对多的关系,因此在这种情况下我似乎无法执行订单。
我的问题:如何按号码对发票行进行排序?
感谢。
答案 0 :(得分:3)
简短回答:你不能。这是实体框架的限制,而不是Breeze。
您无法在EF LINQ查询中使用“展开”过滤,选择或订购您包含的相关实体。
您可能会管理客户端上相关实体的排序顺序,例如订单行项目的显示。
另请注意,Breeze导航路径返回的实体集合是无序的。我不确定如果您尝试对Breeze实体导航集合(例如,Order.LineItems)进行排序会发生什么。我担心这会导致Breeze认为你对实体进行了更改......因为排序似乎会在排序时将实体移除并添加到集合中。事实上,你的EntityManager
会认为有些变化尚未发生变化。
我尝试了一个实验,似乎一切正常。我在Northwind做了类似的事情:
获取客户订单(“让我们停止N店”)
检查了cust.Orders()
的序列;他们有无序订单ID:[10719,10735,10884,10579]
执行了这样一行:cust.Orders().sort(function(left, right){return left.OrderID() < right.OrderID()? -1 : 1})
再次检查cust.Orders()
的序列;这次他们排序:[10579,10719,10735,10884]
检查了客户的EntityManager.hasChanges()
...仍然是假的(没有变化)。
我承认我很高兴。我需要编写一个适当的测试,以确保它可靠地工作。我必须确保Knockout绑定到导航属性以排序顺序显示它们。但到目前为止我受到了鼓励。
重要提示:
Breeze不会对列表进行排序。如果添加新订单或者由于后续查询,Breeze会向集合添加新订单,则必须执行此操作。
- 醇>
您的排序会影响绑定到此导航属性的每个视图。如果您希望每个视图在该集合中拥有自己的实体类型,则必须维护单独的特定于视图的集合,这些集合会影响导航属性集合。
如果我对所有这些都不对,那么你必须为每个ViewModel管理相关实体的影子集合,按照你的意愿排序。
我怀疑我们必须通过调用valueHasMutated
让KO了解排序后的数组更改。我花了15分钟进行实验。它似乎工作正常。
我从ASP.NET SPA模板创建了一个新的KO Todo应用程序(目前有关于缺少jQuery.UI库的虚假投诉,无论如何都是完全不必要的。)
我在delete-TodoList链接上方的 index.cshtml 添加了“排序链接”:
<a href="#" data-bind="click: $parent.sortList">Sort</a>
然后我在 viewModel.js :
中实现了它var sortAscending = true; var viewmodel = { ... sortList: sortList, ... }; ... function sortList(list) { list.todos().sort(function(left, right) { return (sortAscending ? 1 : -1) * (left.title().toLowerCase() < right.title().toLowerCase() ? -1 : 1); }); sortAscending = !sortAscending; // reverse sort direction list.todos.valueHasMutated(); // let KO know that we've sorted }
像魅力一样工作。随意排序,添加,删除待办事项。当我添加和删除时,应用程序会在预期时保存...但在保存期间不会保存。
尝试valueHasMutated
。