我正在尝试使用Entity Framework 6和.NET 4.5.1从我的Webapi2 Breeze控制器获取数据。当我在导航属性上使用Where子句时,得到错误“无法找到属性”。甚至没有对Webapi2控制器进行调用
如果我省略了where子句,则会正确返回数据。
c#类的相关部分:
public class NotificationRule {
public Guid NotificationRuleId { get; set; }
public virtual NotificationRuleSet NotificationRuleSet { get; set; }
}
导航属性NotificationRuleSet中的C#类的相关部分:
public class NotificationRuleSet{
public Guid NotificationRuleSetId { get; set; }
public virtual List<NotificationRule> NotificationRules { get; set; }
}
C#Breeze控制器的相关部分:
public IQueryable<NotificationRuleSet> NotificationRuleSets()
{
return _contextProvider.Context.NotificationRuleSets;
}
public IQueryable<NotificationRule> NotificationRules()
{
return _contextProvider.Context.NotificationRules;
}
Query(Typescript)的相关部分:
var query = breeze.EntityQuery.from("NotificationRules")
.where ("NotificationRuleSet.NotificationRuleSetId","==", this.NotificationRuleSetId)
.expand("NotificationRuleSet");
var Result = this.BreezeEntityManager
.executeQuery(query)
.then((data) => this.RefreshViewModelCallback(data))
.fail((data) => alert("Fail to retrieve data"));
如果我将Where子句退出,正如您在此Fiddler转储中看到的那样正确传输数据:
{
"$id": "1",
"$type": "Imp.Classes.NotificationRule, Imp",
"NotificationRuleId": "11111111-be1e-423c-ac5b-f2c689093aca",
"NotificationRuleSet": {
"$id": "2",
"$type": "Imp.Classes.NotificationRuleSet, Imp",
"NotificationRuleSetId": "11111111-1bd6-4520-9f69-381504b8e2b2",
"NotificationRules": [
{
"$ref": "1"
}
],
},
}
所以我收到一个错误,即属性不存在,但似乎存在。
在非导航属性上使用Where可以正常工作。
我读过有关camelCasing的内容,但用notificationRuleSet替换NotificationRuleSet会产生同样的错误。
编辑: 解决方案似乎是Viewmodels查询中的NotificationRules应该以小写字符开头,无论控制器方法名称的第一个字符是大写还是小写。
答案 0 :(得分:2)
camelCasing很可能是你的问题,只要实体和财产都存在 -
.where('notificationRuleSet.notificationRuleSetId', "==", this.NotificationRuleSetId)
请记住,当您来自CamelCasing您的属性名称时,它也适用于导航属性。
答案 1 :(得分:0)
我认为在审核了你与PW Kad的互动后我得到了解释。
我的猜测是defaultResourceName
类型的实际NotificationRule
是&#34; notificationRules&#34;。
manager.metadataStore.getEntityType('NotificationRule').defaultResourceName;
另一个问题。你说它失败了。什么是失败异常(检查响应的有效负载)。是这样的吗?
$id: "1",
$type: "System.Web.Http.HttpError, System.Web.Http",
Message: "The query specified in the URI is not valid.",
ExceptionMessage: "A binary operator with incompatible types was detected. Found operand types 'Edm.Guid' and 'Edm.String' for operator kind 'Equal'.",
ExceptionType: "Microsoft.Data.OData.ODataException",
这就是我的想法。大多数时候,当查询发送到服务器时,Breeze不需要知道查询的根类型。它可以简单地等待查询结果并通过JSON推断来确定所涉及的类型(或类型)。
但偶尔的查询涉及过滤器比较,其数据类型不明确。 GUID就是一个很好的例子。除非breeze知道查询根类型,否则它无法确定&#34; 11111111-be1e-423c-ac5b-f2c689093aca&#34;在&#34; foo ==&#39; 11111111-be1e-423c-ac5b-f2c689093aca&#39;&#34;应该是字符串或GUID。一个人会猜测它是一个GUID;微风不太确定。只有当你知道&#34; foo&#34;的数据类型时才能确定。属性。
Breeze无论如何都会撰写查询。如果它猜到字符串,如果产生一个看起来像&#34; ... foo eq&#39; 11111111-be1e-423c-ac5b-f2c689093aca&#39; ...&#34;这将失败(无论如何)。
我认为这可能是你的问题。
我在DocCode中尝试了一个我认为可以演示它的实验。我将订单查询的端点名称更改为不是Order
类型的defaultResourceName
(即&#34;订单&#34;)。
实际上,如果网址显示“订单”,则Web API并不关心。或者&#39;订单&#39;所以我可以通过将查询指向&#34; orders&#34;来实现我的目标,即将Breeze与根类型混淆。并且查询仍应由Web API路由到适当的控制器GET方法。
我原以为Breeze会将GUID查询组成一个字符串,因此我可以复制你的问题。这是我的尝试
/*********************************************************
* Orders of Customers with Alfred's ID
* Customer is the related parent of Order
* CustomerID is a GUID
* Demonstrates "nested query", filtering on a related entity
* where the filter criteria is ambiguous (string or GUID)
* and only knowing the root query type (Order) can disambiguate.
* The 'defaultResourceName' for Order is "Orders", not "orders"
* so I expect this test to fail ... but it doesn't ...
* because Breeze disambiguated anyway.
*********************************************************/
test("orders of Customers w/ Alfred's ID (resource name is lowercased)", 2, function () {
var query = EntityQuery.from("orders")
.where("Customer.CustomerID", "==", testFns.wellKnownData.alfredsID)
.expand("Customer");
verifyQuery(newEm, query, "orders query", showOrdersToAlfred);
});
不幸的是,测试通过了!
这是Breeze发送给服务器的URL:
http://localhost:56337/breeze/Northwind/orders?$filter=Customer.CustomerID eq guid'785efa04-cbf2-4dd7-a7de-083ee17b6ad2'&$expand=Customer
DAMN Breeze(v.1.4.12)对我来说太聪明了。它以某种方式弄清楚我的比较值是一个GUID ...尽管不知道查询的根类型。
这意味着我没有解释为什么在您的示例中,breeze.EntityQuery.from("notificationRules")
有效但breeze.EntityQuery.from("NotificationRules")
没有。
一旦你告诉我们defaultResourceName
并向我们展示生成的网址(a)何时起作用,以及(b)何时不起作用,我可能会有另一个想法。