BreezeJs谓词在未映射的属性上表现不同

时间:2015-01-16 21:17:37

标签: breeze

我有一种情况需要为子实体提供自定义数据以及父母的一些属性。这是我的代码:

型号:

public class InvoiceHeader
{

    public int Id { get; set; }
    public short LocationId { get; set; }
    public DateTime EntryDate { get; set; }

    // some other properties

     public Location Location { get; set; }

}

public class InvoiceItemsDto
{

    public int Id { get; set; }
    public int InvoiceHeaderId { get; set; }

    public string ProductName { get; set; } // Not mapped

    // some other properties
    // Added to get the headers entry date and location:

    public short LocationId { get; set; } // Not mapped
    public DateTime EntryDate { get; set; } // Not mapped
}

控制器:

[HttpGet]
    public IQueryable<InvoiceItemsDto> InvoiceItemsHeaders()
    {
        return _contextProvider.Context.InvoiceItems.Select(a => new InvoiceItemsDto()
        {
            Id = a.Id,
            HeaderId = a.HeaderId,
            // Some Other properties
             ProductName = a.Product.ProductName,
            EntryDate = a.InvoiceHeader.EntryDate,
            LocationId = a.InvoiceHeader.LocationId
        });
    }

使用Javascript:

metadataStore.registerEntityTypeCtor(
        'InvoiceItems',InvoiceItemInit , InvoiceItemInitializer);

// Here goes the unmapped properties
function InvoiceItemInit() {
        this.ProductName = "";
        this.LocationId = 0;
        this.EntryDate = new Date();

    }

    //   For Css styling only:
     function InvoiceItemInitializer(Item) {
         Item.isSelected = ko.observable(false);
        Item.isDeleted = ko.observable(false);
        Item.focused = ko.observable(false);
     }


// Action:
var locationId_p = Predicate.create('LocationId', '==', locationId());

var dateFrom_p = Predicate.create('EntryDate', '>=',  dateFrom().toJSON()); // throws an error.

var dateTo_p = Predicate.create('EntryDate', '<=', dateTo().toJSON()); //throws an error.

var ProductName_p = Predicate.create('ProductName', 'contains', productName()); // throws an error.

var whereClause = locationId_p.and(dateFrom_p).and(dateTo_p).and(ProductName_p);

var query = EntityQuery.from('InvoiceItemsHeaders').toType(entityNames.invoiceItem)
               .where(whereClause)
               .skip(skipPage * 50)
               .take(50)
              .orderBy('headerId')
              .inlineCount(true);
        ;

错误是JSON序列化内容(例如,ProductName未被%27%所包围,我相信它是一个字符串指示符)

将谓词的代码更改为:

 var dateFrom_p = Predicate.create('EntryDate', '>=', "datetime'" + dateFrom().toJSON() + "'");

var dateTo_p = Predicate.create('EntryDate', '<=', "datetime'" + dateTo().toJSON() + "'");

var ProductName_p = Predicate.create('ProductName', 'contains', "'" + productName() + "'");

有效..然而,这不适用于映射的属性,因为它们正确地是JSON ..

还有其他方法可以解决这个未映射的日期和字符串吗?

修改

我已经编辑了原始帖子,用于纠正(仅限)Pascal和驼峰案例 (我的坏)

澄清:

  1. 谓词中提到的所有属性都是未映射的 即LocationIdProductNameEntryDate,这就是他们必须使用PascalCase的原因。

  2. 我遇到的问题是关于这些属性的谓词(LocationId(int type)除外)

  3. locationId()dateFrom()dateTo()productName()是可观察者&#39;用户输入/选择的值

  4. 使用以下谓词执行查询:

    Predicate.create('EntryDate', '>=', dateFrom());
    
    Predicate.create('EntryDate', '<=', dateTo());
    
  5. 导致以下错误:

    "')' or operator expected at position 65 in '(((LocationId eq 1) and (EntryDate ge Mon Feb 02 2009 00:00:00 GMT+0300 (Arab Standard Time))) and (EntryDate le Sun Jan 18 2015 04:04:46 GMT+0300 (Arab Standard Time))'."
    

    生成的网址:

    http://localhost:8743/breeze/breeze/InvoiceItemsHeaders?$filter=(((LocationId%20eq%201)%20and%20(EntryDate%20ge%20Mon%20Feb%2002%202009%2000%3A00%3A00%20GMT%2B0300%20(Arab%20Standard%20Time)))%20and%20(EntryDate%20le%20Sun%20Jan%2018%202015%2003%3A18%3A28%20GMT%2B0300%20(Arab%20Standard%20Time))&$orderby=HeaderId&$top=50&$inlinecount=allpages
    

    P.S。我没有在datetime类型的映射属性上获得此错误,所有(已映射或未映射)属性值都来自已知的jquery日历,供用户选择所需的日期。

    所以我必须使用toJson()以适当的Json格式修复datetime格式:

    console.log(dateFrom());// Mon Feb 02 2009 00:00:00 GMT+0300 (Arab Standard Time)
    
    console.log(dateFrom().toJSON());// 2009-02-01T21:00:00.000Z
    

    我已经欺骗了来自datetime类型的映射属性的谓词的正确网址,然后我必须提出以下内容才能使查询正常工作:

    Predicate.create('EntryDate', '>=', "datetime'" + dateFrom().toJSON() + "'");
    
    Predicate.create('EntryDate', '<=', "datetime'" + dateTo().toJSON() + "'");
    

    对于字符串类型的其他未映射属性ProductName,场景有点不同,使用以下谓词运行:

    Predicate.create('ProductName', 'contains', productName());
    

    结果:

    错误讯息:

    "Could not find a property named 'abc' on type 'BreezeProj.InvoiceItemsDTO'"
    

    URL:

    http://localhost:8743/breeze/breeze/InvoiceItemsHeaders?$filter=(substringof(abc%2CProductName)%20eq%20true)
    

    &#39; ABC&#39;这是传递给ProductName()

    的值

    同样,我必须提出以下信息才能使查询正常工作:

    Predicate.create('ProductName', 'contains', "'" + productName() + "'");
    

    有什么想法? 感谢

    我对沃德第二次编辑的回应:

    InvoiceItems是entityType,它是如何在数据库中命名的,我使用InvoiceItemsDto 作为获得所需属性的视图。我可以简单地为InvoiceHeader扩展EntryDate,为Location扩展ProductProductName 但我会发现自己在客户端多次扩展许多其他导航属性,这很麻烦。

    EntryDate - 例如 - 是映射到InvoiceItemsDto但未映射到实际实体InvoiceItems的属性,因此entityNames.invoiceItemInvoiceItems < / p>

    发布上面的整个代码并不意味着我希望你被我的应用程序的漩涡所吸引。

    也许我没有能力清除我的意图,但是 我的问题确实很小而且很专注&#34;为什么Breeze没有意识到&#34;未映射的数据类型&#34;具有谓词的属性何时在查询结果中实现它们? &#34;

    无论如何,这是指向您要求的元数据的链接:

    http://pastebin.com/KGZKFLUU

    再次,抱歉不便。

1 个答案:

答案 0 :(得分:1)

我的头部有太多的活动部件缠绕在这里。你在谈论多个未指明的错误。你有谓词触及多个属性,我无法分辨哪些是有问题的。您声明其中一个映射属性(productName)的序列化错误,但没有说明该错误是什么(“JSON序列化内容”不计算在内)。

如果您可以将其分解为一个专注于一个问题的小型可执行(例如,plunker)样本,那将是理想的。摆脱无关紧要的一切(例如,InvoiceItemInitializer,查询中令人分心的条款)。

一些事情从页面上跳了出来:

  • InvoiceItemInit定义了ProductName(PascalCase),但您的查询谓词将其显示为productName(camelCase),其他属性似乎是驼峰。

  • 如果服务器上的某个属性未映射,我不希望Breeze允许指定该属性的查询(不确定该属性,但似乎有问题)。

  • 您没有向我们展示针对感兴趣的实体的客户端上的相关EntityType元数据,因此我们无法确切地知道发生了什么。

  • 为什么.toJson调用谓词比较值?你以前在哪里见过的?我自己也没有这样做,也没有在任何示例代码中看到它。

  • 为什么比较值来自函数?为什么productName()代替productName'foo'

当你做一些非常不寻常的事情时,我们很难猜到你走了哪条路。 可执行的repro可能是您获得答案的最佳机会

我对您1月16日回复的回复

那更好,谢谢。

但很多事情对我来说仍然没有意义。最重要的差距:我看不到您的客户端元数据所以我不知道Breeze认为EntityTypes涉及到什么。

  

请不管你做什么,都不要在这里完整地粘贴你的元数据。将其放在pastebingist中,并在您的问题中引用它。

您为'InvoiceItems'注册了一个ctor,但据我所知,这不是EntityType。 'InvoiceItems'看起来更像是资源名称,查询的目标;它显然不是类型名称(类型名称通常是单数,顺便说一句)。

我看到你正在投射查询:.toType(entityNames.invoiceItem)。什么是entityNames.invoiceItem

我不明白为什么你希望'InvoiceItems'被视为EntityType。我认为它与InvoiceItemsDto有关,但我不知道Breeze如何知道这一点。

我不知道为什么在将属性明确映射到InvoiceItemsDto的属性时,首先将属性创建为未映射的属性。 InvoiceItemsDtoInvoiceItems与<{1}}基本上存在脱节。

我承认我也不明白为什么Breeze没有意识到你的ctor中定义的“未映射”属性的数据类型。但由于其他一切都不对,我不确定发生了什么。

也许您可以退一步告诉我为什么您首先拥有DTO,以及为什么您要隐藏并显示实际位于InvoiceHeader商务舱的属性。

我害怕听到答案,因为我觉得自己被吸入了应用程序的漩涡中。这不是我们在S.O.做的。我们回答小问题;我们不会涉及人们的申请。

这就是为什么提供一次只能解决一个问题的工作样本非常重要的原因。

原谅我突然的语言。我不是故意这么粗鲁。这对我来说已经很晚了,当有这么多动人和失踪的作品时,我感到很沮丧,我感到很沮丧。

您可能需要考虑与IdeaBlade进行简短的专业服务,以帮助您重回正轨。