【问题标题】:BreezeJs predicates behave differently on unmapped propertiesBreezeJs 谓词在未映射的属性上表现不同
【发布时间】:2015-01-19 01:26:50
【问题描述】:

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

型号:

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 类型)除外)

  3. locationId()dateFrom()dateTo()productName() 是用户输入/选择的 observables 值

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

    Predicate.create('EntryDate', '>=', dateFrom());
    
    Predicate.create('EntryDate', '<=', dateTo());
    

导致以下错误:

"')' 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

附:我没有在 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 类型映射属性的谓词的正确 url,然后我必须想出以下内容才能使查询正常工作:

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'"

网址:

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

这里的'abc'是一个传递给ProductName()的值

再次,我必须提出以下查询才能正常工作:

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

有什么想法吗? 谢谢

我对 Ward 的第二次修改的回应:

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

EntryDate - 例如 - 是映射到 InvoiceItemsDto 但不映射到应计实体 InvoiceItems 的属性,因此,entityNames.invoiceItemInvoiceItems

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

也许我缺乏清除意图的能力,但是 我的问题确实很小而且很集中“为什么 Breeze 在查询结果中实现了谓词时没有实现带有谓词的“未映射”属性的数据类型?”

无论如何,这里是您请求的元数据的链接:

http://pastebin.com/KGZKFLUU

再次,抱歉给您带来不便。

【问题讨论】:

    标签: breeze


    【解决方案1】:

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

    如果您可以将其分解为一个专注于一个问题的小型可执行(例如 plunker)示例,那将是理想的选择。去掉所有无关紧要的东西(例如,InvoiceItemInitializer,查询中分散注意力的子句)。

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

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

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

    • 您没有在客户端上向我们展示感兴趣实体的相关 EntityType 元数据,因此我们无法真正了解发生了什么。

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

    • 为什么比较值来自函数?为什么是productName() 而不是productName'foo'

    当你做了非常不寻常的事情时,我们很难猜出你是从哪里走出来的。 可执行的重现可能是您获得答案的最佳机会

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

    这样更好,谢谢。

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

    无论您做什么,请不要将您的元数据完整粘贴到此处。将其放入 pastebingist 并在您的问题中引用它。

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

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

    我不明白您为什么希望将“InvoiceItems”视为EntityType。我有点明白它与InvoiceItemsDto 有关,但我不明白微风怎么会知道这一点。

    我不知道为什么当它们清楚地映射到InvoiceItemsDto 的属性时,你为什么首先创建未映射的属性。 InvoiceItemsDtoInvoiceItems 有一些根本上的脱节。

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

    也许您可以退后一步,告诉我为什么您首先拥有 DTO,以及为什么您试图隐藏和显示实际上在您的 InvoiceHeader 业务类上的属性。

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

    这就是为什么提供一次仅限于一个问题的工作示例对您来说如此重要的原因。

    请原谅我生硬的语言。我不想这么粗鲁。对我来说也太晚了,当有这么多移动和缺失的部分时,我无能为力而感到沮丧。

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

    【讨论】:

    • 对不起,Ward,我昨晚匆忙发布了我的问题,有点困(真是一团糟!)。我对 plunker 不熟悉,所以这次我试图更具体、更准确。我已经编辑了我的问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多