I have a situation when I needed to bring custom data for child entities along with some properties from their parents..Here is my Code:
Models:
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
}
Controller:
[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);
;
The errors are JSON serialization stuff (e.g. ProductName is not surrounded with %27% which I believe it's a string indicator)
Changing the code for predicates to:
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() + "'");
works.. However, that does not apply to mapped properties as they are being JSON'd correctly..
Is there any other way to work around this unmapped dates and strings?
EDIT:
I have edited the original post for correcting (ONLY) the Pascal and camel cases (my bad)
To clarify:
All the mentioned properties within the predicates are unmapped i.e
LocationId,ProductNameandEntryDatethat's why they have to be in PascalCase.The problem I get is with predicates on those properties (Except for
LocationId(int type))locationId(),dateFrom(),dateTo()andproductName()are the observables' values which the user types/choosesExecuting the query with the following predicates:
Predicate.create('EntryDate', '>=', dateFrom()); Predicate.create('EntryDate', '<=', dateTo());
results in the following error:
"')' 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))'."
URL Generated:
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. I don't get this error on a mapped property of type datetime which all (mapped or unmapped) properties values come from the known jquery calender for the user to choose the desired dates.
So I had to use the toJson() to fix the datetime format in an appropriate Json format:
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
I've cheated the correct url that comes from a predicate on a mapped property of type datetime then I had to come up with the following in order to make the query work:
Predicate.create('EntryDate', '>=', "datetime'" + dateFrom().toJSON() + "'");
Predicate.create('EntryDate', '<=', "datetime'" + dateTo().toJSON() + "'");
As for the other unmapped property ProductName which is of type string the scenario is a bit different, running with the following predicate:
Predicate.create('ProductName', 'contains', productName());
Results in:
Error message:
"Could not find a property named 'abc' on type 'BreezeProj.InvoiceItemsDTO'"
url:
http://localhost:8743/breeze/breeze/InvoiceItemsHeaders?$filter=(substringof(abc%2CProductName)%20eq%20true)
'abc' here is a value passed to ProductName()
Again, I had to come up with the following for the query to work:
Predicate.create('ProductName', 'contains', "'" + productName() + "'");
Any thoughts? Thanks
My response to Ward's second edit:
InvoiceItems is the entityType, that's how it's named in the database, I used InvoiceItemsDto
as a view to get the properties needed. I could've simply expanded the InvoiceHeader for EntryDate and Location or Product for ProductName
but I would find myself expanding many other navigation properties many times at the client side, which is troublesome.
EntryDate - for instance- is a property that is mapped to InvoiceItemsDto but not to the acrual entity InvoiceItems, hence, entityNames.invoiceItem is InvoiceItems
Posting the whole code above does not mean I want you to get sucked into the vortex of my application.
Perhaps I lack the ability to clear out my intentions, but my question is indeed small and focused "Why Breeze didn't realize the data types of the "unmapped" properties with predicates when it does realize them in query results? "
Anyways, here is a link to the metadata you've requested:
again, Sorry for inconvience.