
рдкрд░рдВрдкрд░рд╛рдЧрдд рд░реВрдк рд╕реЗ, рдбреЗрдЯрд╛ рдкрд░ рдУрдбрд╛рдЯрд╛ рдкреНрд░рд╢реНрдиреЛрдВ рдХреЛ рд╕рдВрдХрд▓рди рдХреЗ рджреМрд░рд╛рди рдпрд╛ рдЗрдВрдЯреЗрд▓реАрд╕реЗрдирд╕ рд╕рдорд░реНрдерди рдХреЗ рдмрд┐рдирд╛ рдЯрд╛рдЗрдкрд┐рдВрдЧ рдХреЗ рдмрд┐рдирд╛ рд╕рд░рд▓ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЗ рд░реВрдк рдореЗрдВ рд╡реНрдпрдХреНрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдбреЗрд╡рд▓рдкрд░ рдХреЛ рдХреНрд╡реЗрд░реА рднрд╛рд╖рд╛ рдХреЗ рд╕рд┐рдВрдЯреИрдХреНрд╕ рдХреЛ рд╕реАрдЦрдирд╛ рд╣реЛрдЧрд╛ред рдпрд╣ рд▓реЗрдЦ TsTOOdata рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддрд╛ рд╣реИ, рдЬреЛ рдкреНрд░рд╢реНрдиреЛрдВ рдХреЛ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рднрд╛рд╖рд╛ рдирд┐рд░реНрдорд╛рдг рдореЗрдВ рдмрджрд▓ рджреЗрддрд╛ рд╣реИ рдФрд░ рдХрдХреНрд╖рд╛рдУрдВ рдФрд░ рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЗ рд╕рдорд╛рди рд▓рд╛рдЧреВ рд╣реЛрддрд╛ рд╣реИред рдЖрдк рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреАрд╡рд░реНрдб рдФрд░ рдкрд░рд┐рдЪрд┐рдд рдСрдкрд░реЗрдЯрд░реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЯрд╛рдЗрдк рдХрд┐рдП рдЧрдП рдкреНрд░рд╢реНрди рдмрдирд╛рддреЗ рд╣реИрдВред
TsToOdata рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЗ рд▓рд┐рдП рдПрдХ рдкреБрд╕реНрддрдХрд╛рд▓рдп рд╣реИред рдпрд╣ C # рдХреЗ рд▓рд┐рдП LINQ рдХреЗ рд╕рдорд╛рди рд╣реИ, рд▓реЗрдХрд┐рди рдмрд╛рдж рд╡рд╛рд▓реЗ рдХреЗ рд╡рд┐рдкрд░реАрдд, рдпрд╣ рдХреЗрд╡рд▓ OData рдкреНрд░рд╢реНрдиреЛрдВ рдХреЗ рд▓рд┐рдП рд╣реИред рдбреЗрд╡рд▓рдкрд░ рдЬреЛ рдХреНрд╡реЗрд░реА рдмрдирд╛рддрд╛ рд╣реИ, рдХреЗ рд▓рд┐рдП TsTOOdata рдХрд╛ рд╕рдмрд╕реЗ рд╕реНрдкрд╖реНрдЯ рд╣рд┐рд╕реНрд╕рд╛ рдХреНрд╡реЗрд░реА рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рд╣реИред рдХреНрд╡реЗрд░реА рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐рдпрд╛рдБ рдШреЛрд╖рдгрд╛рддреНрдордХ рд╡рд╛рдХреНрдпрд╡рд┐рдиреНрдпрд╛рд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреА рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рдбреЗрд╡рд▓рдкрд░ рд▓рд┐рдЦрддреЗ рд╣реИрдВ рдХрд┐ рдХреНрдпрд╛ рдХрд░рдирд╛ рд╣реИ, рдпрд╣ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдиреЗ рдХреЗ рдмрд┐рдирд╛ рдХрд┐ рдпрд╣ рдХреИрд╕реЗ рдХрд░рдирд╛ рд╣реИред рдХреНрд╡реЗрд░реА рд╕рд┐рдВрдЯреИрдХреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ, рдЖрдк рдкреНрд░реЛрдЧреНрд░рд╛рдо рдХреЛрдб рдХреА рдПрдХ рдиреНрдпреВрдирддрдо рд░рд╛рд╢рд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдбреЗрдЯрд╛ рд╕реНрд░реЛрдд рд╕реЗ рдбреЗрдЯрд╛ рдХреЛ рдлрд╝рд┐рд▓реНрдЯрд░, рд╡реНрдпрд╡рд╕реНрдерд┐рдд рдФрд░ рд╕рдореВрд╣рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
TsTOOdata рд╕реНрдерд╛рдкрд┐рдд рдХрд░реЗрдВ
npm install ts2odata
рдбреЗрдЯрд╛ рдореЙрдбрд▓ рдмрдирд╛рдирд╛
рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдореЗрдВ рдЯрд╛рдЗрдкрдХрд╛рд╕реНрдЯ рдХрдХреНрд╖рд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдУрдбрдЯрд╛ рд╕реНрдХреАрдорд╛ рдХреА рдореИрдкрд┐рдВрдЧ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
рдкрд╣рд▓рд╛ рдХрджрдо рдкрд╣рд▓реЗ рдИрдбреАрдПрдордПрдХреНрд╕ рдЬреЛрдВрд╕рди рд╕реЗ рд╕реНрдХреАрдорд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рд╣реИред рдЗрд╕рдХреЗ рд▓рд┐рдП рдЖрдк OdataToEntity рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ ред
IEdmModel edmModel;
using (var reader = XmlReader.Create("edmx_schema.xml"))
edmModel = CsdlReader.Parse(reader);
var generator = new OeJsonSchemaGenerator(edmModel);
using (var utf8Json = new MemoryStream())
{
generator.Generate(utf8Json);
utf8Json.Position = 0;
File.WriteAllBytes("json_schema.json", utf8Json.ToArray());
}
Json TypeScript. quicktype.
.
import { EntitySet, OdataContext } from 'ts2odata';
import * as oe from './order';
export class OrderContext extends OdataContext<OrderContext> {
Categories = EntitySet.default<oe.Category>();
Customers = EntitySet.default<oe.Customer>();
OrderItems = EntitySet.default<oe.OrderItem>();
OrderItemsView = EntitySet.default<oe.OrderItemsView>();
Orders = EntitySet.default<oe.Order>();
}
let context: OrderContext = OdataContext.create(OrderContext, 'http://localhost:5000/api');
context.Orders;
context.Orders.select(o => { return { p: o.Name } });
context.Orders.orderby(i => i.Id);
context.Orders.orderbyDescending(i => i.Id);
context.Orders.filter(o => o.Date.getFullYear() == 2016);
context.Orders.expand(o => o.Items);
context.Customers.expand(c => c.Orders).thenExpand(o => o.Items);
context.Orders.orderby(i => i.Id).skip(2);
context.Orders.orderby(i => i.Id).top(3);
context.OrderItems.groupby(i => { return { Product: i.Product } });
context.OrderItems.groupby(i => { return { OrderId: i.OrderId, Status: i.Order.Status } })
.select(g => {
return {
orderId: g.key.OrderId,
avg: g.average(i => i.Price),
dcnt: g.countdistinct(i => i.Product),
max: g.max(i => i.Price),
max_status: g.max(_ => g.key.Status),
min: g.min(i => i.Price),
sum: g.sum(i => i.Price),
cnt: g.count()
}});
context.Customers.key({ Country: 'RU', Id: 1 });
context.OrderItems.key(1, i => i.Order.Customer);
context.OrderItems
.select(i => {
return {
product: i.Product,
Total: i.Count * i.Price,
SumId: i.Id + i.OrderId
}
});
context.Orders.filter(o => o.Items.every(i => i.Price >= 2.1));
context.Orders.filter(o => o.Items.some(i => i.Count > 2));
IN
let items = [1.1, 1.2, 1.3];
context.OrderItems.filter(i => items.includes(i.Price), { items: items });
context.Orders.count();
asEntitySet
context.Orders(o => o.AltCustomer).thenSelect(o => {{
p1: o.Address,
: o.Country,
: o.Id,
: o.Name,
: o.Sex
}}).asEntitySet().orderby(o => o.Id)
GitHub.
, select, expand, groupby тАФ тАФ , , then: thenFilter, thenExpand, thenOrderby, thenOrderbyDescending, thenSkip, thenTop. select thenSelect , , , asEntitySet.
тАФ filter/thenFilter, тАФ select/thenSelect, тАФ groupby , .
let count: number | null = null;
context.OrderItems.filter(i => i.Count == count, { count: count });
let s = {
altCustomerId: 3,
customerId: 4,
dateYear: 2016,
dateMonth: 11,
dateDay: 20,
date: null,
name: 'unknown',
status: "OdataToEntity.Test.Model.OrderStatus'Unknown'",
count1: 0,
count2: null,
price1: 0,
price2: null,
product1: 'unknown',
product2: 'null',
orderId: -1,
id: 1
};
context.Orders.filter(o => o.AltCustomerId == s.altCustomerId &&
o.CustomerId == s.customerId &&
(o.Date.getFullYear() == s.dateYear &&
o.Date.getMonth() > s.dateMonth &&
o.Date.getDay() < s.dateDay ||
o.Date == s.date) &&
o.Name.includes(s.name) &&
o.Status == s.status, s)
.expand(o => o.Items)
.thenFilter(i => (i.Count == s.count1 ||
i.Count == s.count2) &&
(i.Price == s.price1 ||
i.Price == s.price2) &&
(i.Product.includes(s.product1) ||
i.Product.includes(s.product2)) &&
i.OrderId > s.orderId &&
i.Id != s.id, s);
OdataFunctions.stringLength
context.Customers.filter(c => OdataFunctions.stringLength(c.Name) == 5);
OdataFunctions.arrayLength
context.Orders.filter(o => OdataFunctions.arrayLength(o.Items) > 2);
select, filter getQueryUrl toArrayAsync.
getQueryUrl URL . TypeScript:
let url: URL = context.Customers
.expand(c => c.AltOrders).thenExpand(o => o.Items).thenOrderby(i => i.Price)
.expand(c => c.AltOrders).thenExpand(o => o.ShippingAddresses).thenOrderby(s => s.Id)
.expand(c => c.Orders).thenExpand(o => o.Items).thenOrderby(i => i.Price)
.expand(c => c.Orders).thenExpand(o => o.ShippingAddresses).thenOrderby(s => s.Id)
.orderby(c => c.Country).orderby(c => c.Id).getQueryUrl();
OData :
http://localhost:5000/api/Customers?$expand=
AltOrders($expand=Items($orderby=Price),ShippingAddresses($orderby=Id)),
Orders($expand=Items($orderby=Price),ShippingAddresses($orderby=Id))
&$orderby=Country,Id
toArrayAsync Json. TypeScript:
context.Customers
.expand(c => c.Orders).thenSelect(o => { return { Date: o.Date } }).orderby(o => o.Date)
.asEntitySet().select(c => { return { Name: c.Name } }).orderby(c => c.Name).toArrayAsync();
Json:
[{
"Name": "Ivan",
"Orders": [{
"Date": "2016-07-04T19:10:10.8237573+03:00"
}, {
"Date": "2020-02-20T20:20:20.000002+03:00"
}
]
}, {
"Name": "Natasha",
"Orders": [{
"Date": "2016-07-04T19:10:11+03:00"
}
]
}, {
"Name": "Sasha",
"Orders": []
}, {
"Name": "Unknown",
"Orders": [{
"Date": null
}
]
}
]
, , toArrayAsync OdataParser:
import { OdataParser } from 'ts2odata';
import schema from './schema.json';
let odataParser = new OdataParser(schema);
context.Orders.toArrayAsync(odataParser);
(enum)
OData (Namespace), :
let context: OrderContext = OdataContext.create(OrderContext, 'http://localhost:5000/api', 'OdataToEntity.Test.Model');
рдХреБрдЫ рдорд╛рдорд▓реЛрдВ рдореЗрдВ, рдПрдиреНрдпреВрдорд░реЗрд╢рдВрд╕ рдХрд╛ рдареАрдХ рд╕реЗ рдЕрдиреБрд╡рд╛рдж рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдУрдбрд┐рдЯрдкреИрд░рд╕рд░ рдСрдмреНрдЬреЗрдХреНрдЯ рдмрдирд╛рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ ред
import { OdataParser } from 'ts2odata';
import schema from './schema.json';
let odataParser = new OdataParser(schema);
let context: OrderContext = OdataContext.create(OrderContext, 'http://localhost:5000/api', 'OdataToEntity.Test.Model', odataParser);
рд╕реНрд░реЛрдд
рд╕реНрд░реЛрдд рдХреЛрдб GitHub рдкрд░ рд╣реИ ред
рд╕реНрд░реЛрдд рдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ - рдкрд░реАрдХреНрд╖рдг рдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ рдкреИрдХреЗрдЬ рдХрд╛ рдиреЛрдб рдХреЛрдб - рдкрд░реАрдХреНрд╖рдгред
рдореБрдЭреЗ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдореЗрд░рд╛ TsTOdata рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдЖрдкрдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧреА рд╣реЛрдЧрд╛ рдФрд░ рдЖрдкрдХреЛ рдиреАрд░рд╕ рдХреЛрдб рд▓рд┐рдЦрдиреЗ рдХреА рджрд┐рдирдЪрд░реНрдпрд╛ рд╕реЗ рдмрдЪрд╛рдПрдЧрд╛ред