Skip to content

Commit 12de455

Browse files
committed
Added OData in IVS demo
Added nometadata and minimal metadata OData services in IVS demo. Minor update in bcp (Belgrade Demo)
1 parent b33a758 commit 12de455

File tree

6 files changed

+277
-7
lines changed

6 files changed

+277
-7
lines changed
Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,23 @@
11
<#@ output extension=".sql" #>
22
<#@ template language="C#" hostspecific="True" #>
3-
43

54
SELECT *
65
FROM OPENROWSET(BULK '<#=this.Host.ResolvePath("..\\logs") #>\log-20170203.ndjson',
7-
FORMATFILE = '<#=this.Host.ResolvePath("..\\logs") #>\linedelimited.fmt' );
6+
FORMATFILE = '<#=this.Host.ResolvePath("..\\logs") #>\linedelimited.fmt' ) as logs;
7+
8+
9+
10+
DROP TABLE IF EXISTS Logs
11+
12+
--{"Timestamp":"2017-02-03T08:33:32.0776155+01:00","Level":"Information","MessageTemplate":"{HostingRequestFinished:l}","Properties":{"ElapsedMilliseconds":154.2332,"StatusCode":200,"ContentType":null,"HostingRequestFinished":"Request finished in 154.2332ms 200 ","EventId":{"Id":2},"SourceContext":"Microsoft.AspNetCore.Hosting.Internal.WebHost","RequestId":"0HL2C0RQ64LNN","RequestPath":"/"},"Renderings":{"HostingRequestFinished":[{"Format":"l","Rendering":"Request finished in 154.2332ms 200 "}]}}
13+
CREATE TABLE Logs (
14+
Data NVARCHAR(MAX),
15+
Timestamp AS CAST(JSON_VALUE(Data, '$.Timestamp') as datetime2),
16+
Level AS CAST(JSON_VALUE(Data, '$.Level') as nvarchar(40)),
17+
ElapsedMilliseconds AS CAST(JSON_VALUE(Data, '$.Properties.ElapsedMilliseconds') AS float),
18+
StatusCode AS CAST(JSON_VALUE(Data, '$.Properties.StatusCode') AS int)
19+
)
820

21+
BULK INSERT Logs
22+
FROM '<#=this.Host.ResolvePath("..\\logs") #>\log-20170203.ndjson'
23+
WITH (FORMATFILE = '<#=this.Host.ResolvePath("..\\logs") #>\linedelimited.fmt')
Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
using Belgrade.SqlClient;
2+
using Microsoft.AspNetCore.Mvc;
3+
using SqlServerRestApi;
4+
using System;
5+
using System.Text;
6+
using System.Threading.Tasks;
7+
8+
// For more information on enabling Web API for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860
9+
namespace Register.Controllers
10+
{
11+
[Route("api/[controller]")]
12+
public class ODataController : Controller
13+
{
14+
IQueryPipe pipe = null;
15+
TableSpec tableSpec = new TableSpec("dbo", "People")
16+
.AddColumn("id", "int", isKeyColumn: true)
17+
.AddColumn("name","nvarchar")
18+
.AddColumn("surname","nvarchar")
19+
.AddColumn("address", "nvarchar")
20+
.AddColumn("town", "nvarchar");
21+
22+
23+
public string ODataMetadataUrl
24+
{
25+
get
26+
{
27+
return this.Request.Scheme + "://" + this.Request.Host + "/api/odata";
28+
}
29+
}
30+
31+
public ODataController(IQueryPipe sqlQueryService)
32+
{
33+
this.pipe = sqlQueryService;
34+
}
35+
36+
[Produces("application/json; odata.metadata=minimal")]
37+
[HttpGet]
38+
public string Get()
39+
{
40+
try
41+
{
42+
return ODataHandler.GetRootMetadataJsonV4(ODataMetadataUrl, new TableSpec[] { tableSpec });
43+
} catch (Exception ex)
44+
{
45+
return ex.Message;
46+
}
47+
}
48+
49+
50+
[Produces("application/xml")]
51+
[HttpGet("$metadata")]
52+
public string Metadata()
53+
{
54+
try {
55+
return ODataHandler.GetMetadataXmlV4(new TableSpec[] { tableSpec }, "Demo.Models");
56+
} catch (Exception ex)
57+
{
58+
return ex.Message;
59+
}
60+
}
61+
62+
// GET api/odata/People
63+
[HttpGet("People")]
64+
public async Task People()
65+
{
66+
await this
67+
.ODataHandler(tableSpec, this.pipe, ODataHandler.Metadata.MINIMAL)
68+
.OnError(ex => Response.Body.Write(Encoding.UTF8.GetBytes(ex.Message), 0, (ex.Message).Length))
69+
.Get();
70+
}
71+
72+
// GET api/odata/People/$count
73+
[HttpGet("People/$count")]
74+
public Task PeopleCount()
75+
{
76+
return this.People();
77+
}
78+
79+
/// <summary>
80+
/// Endpoint that exposes People information using OData protocol.
81+
/// </summary>
82+
/// <returns>OData response.</returns>
83+
// GET api/OData/People
84+
[HttpGet("Product")]
85+
public async Task OData()
86+
{
87+
Response.ContentType = "application/json;odata.metadata=minimal;odata=minimalmetadata";
88+
//var body = Encoding.UTF8.GetBytes(@"{""@odata.context"":""http://localhost:59934/api/odata/$metadata#Product"",""value"":[{""id"":1,""name"":""Test""}]}");
89+
90+
//await Response.Body.WriteAsync(body, 0, body.Length);
91+
92+
await this
93+
.ODataHandler(tableSpec, pipe)
94+
.Get();
95+
}
96+
97+
98+
99+
/// <summary>
100+
/// Method that process server-side processing JQuery DataTables HTTP request
101+
/// and returns data that should be shown.
102+
/// </summary>
103+
/// <returns></returns>
104+
// GET api/People
105+
//[HttpGet]
106+
public string GetOld()
107+
{
108+
//Response.ContentType = "application/json;odata=minimalmetadata;streaming=true;charset=utf-8";
109+
110+
//return "{\"odata.metadata\":\"http://services.odata.org/V3/Northwind/Northwind.svc/$metadata\",\"value\":[{\"name\":\"People\",\"url\":\"People\"}]}";
111+
//Response.ContentType = "application/json;odata=nometadata;streaming=true;charset=utf-8";
112+
//return "{\"odata.metadata\":\"http://services.odata.org/V3/Northwind/Northwind.svc/$metadata\",\"value\":[{\"name\":\"People\",\"url\":\"People\"}]}";
113+
114+
// radi:
115+
//Response.ContentType = "application/xml;charset=utf-8";
116+
//return @"<?xml version=""1.0"" encoding=""utf-8""?><service xml:base=""http://services.odata.org/V3/Northwind/Northwind.svc/"" xmlns=""http://www.w3.org/2007/app"" xmlns:atom=""http://www.w3.org/2005/Atom""><workspace><atom:title>Default</atom:title><collection href=""Categories""><atom:title>Categories</atom:title></collection><collection href=""CustomerDemographics""><atom:title>CustomerDemographics</atom:title></collection><collection href=""Customers""><atom:title>Customers</atom:title></collection><collection href=""Employees""><atom:title>Employees</atom:title></collection><collection href=""Order_Details""><atom:title>Order_Details</atom:title></collection><collection href=""Orders""><atom:title>Orders</atom:title></collection><collection href=""Products""><atom:title>Products</atom:title></collection><collection href=""Regions""><atom:title>Regions</atom:title></collection><collection href=""Shippers""><atom:title>Shippers</atom:title></collection><collection href=""Suppliers""><atom:title>Suppliers</atom:title></collection><collection href=""Territories""><atom:title>Territories</atom:title></collection><collection href=""Alphabetical_list_of_products""><atom:title>Alphabetical_list_of_products</atom:title></collection><collection href=""Category_Sales_for_1997""><atom:title>Category_Sales_for_1997</atom:title></collection><collection href=""Current_Product_Lists""><atom:title>Current_Product_Lists</atom:title></collection><collection href=""Customer_and_Suppliers_by_Cities""><atom:title>Customer_and_Suppliers_by_Cities</atom:title></collection><collection href=""Invoices""><atom:title>Invoices</atom:title></collection><collection href=""Order_Details_Extendeds""><atom:title>Order_Details_Extendeds</atom:title></collection><collection href=""Order_Subtotals""><atom:title>Order_Subtotals</atom:title></collection><collection href=""Orders_Qries""><atom:title>Orders_Qries</atom:title></collection><collection href=""Product_Sales_for_1997""><atom:title>Product_Sales_for_1997</atom:title></collection><collection href=""Products_Above_Average_Prices""><atom:title>Products_Above_Average_Prices</atom:title></collection><collection href=""Products_by_Categories""><atom:title>Products_by_Categories</atom:title></collection><collection href=""Sales_by_Categories""><atom:title>Sales_by_Categories</atom:title></collection><collection href=""Sales_Totals_by_Amounts""><atom:title>Sales_Totals_by_Amounts</atom:title></collection><collection href=""Summary_of_Sales_by_Quarters""><atom:title>Summary_of_Sales_by_Quarters</atom:title></collection><collection href=""Summary_of_Sales_by_Years""><atom:title>Summary_of_Sales_by_Years</atom:title></collection></workspace></service>";
117+
118+
Response.ContentType = "application/xml;charset=utf-8";
119+
return @"<?xml version=""1.0"" encoding=""utf-8""?><service xml:base=""http://localhost:59934/api/odata"" xmlns=""http://www.w3.org/2007/app"" xmlns:atom=""http://www.w3.org/2005/Atom""><workspace><atom:title>Default</atom:title><collection href=""Product""><atom:title>Product</atom:title></collection></workspace></service>";
120+
}
121+
122+
//[HttpGet("$metadata")]
123+
//public string Metadata1()
124+
//{
125+
// Response.ContentType = "application/xml;charset=utf-8";
126+
127+
// return ODataMetaData(this.tableSpec, "Models", "Product");
128+
129+
//}
130+
131+
132+
[HttpGet("$metadata2")]
133+
public string Metadata2()
134+
{
135+
//Response.ContentType = "application/json;odata=minimalmetadata;streaming=true;charset=utf-8";
136+
137+
//return "{\"odata.metadata\":\"http://services.odata.org/V3/Northwind/Northwind.svc/$metadata\",\"value\":[{\"name\":\"People\",\"url\":\"People\"}]}";
138+
//Response.ContentType = "application/json;odata=minimalmetadata;streaming=true;charset=utf-8";
139+
//return "{\"odata.metadata\":\"http://services.odata.org/V3/Northwind/Northwind.svc/$metadata\",\"value\":[{\"name\":\"Categories\",\"url\":\"Categories\"}]}";
140+
Response.ContentType = "application/xml;charset=utf-8";
141+
142+
//var wc = new System.Net.WebRequest();
143+
144+
145+
return @"<?xml version=""1.0"" encoding=""utf-8""?>
146+
<edmx:Edmx Version=""4.0"" xmlns:edmx=""http://docs.oasis-open.org/odata/ns/edmx"">
147+
<edmx:DataServices>
148+
<Schema Namespace=""Models"" xmlns=""http://docs.oasis-open.org/odata/ns/edm"">
149+
<EntityType Name=""Product"">
150+
<Key>
151+
<PropertyRef Name=""id""/>
152+
</Key>
153+
<Property Name=""id"" Type=""Edm.Int32""/>
154+
<Property Name=""name"" Type=""Edm.String"" />
155+
</EntityType>
156+
</Schema>
157+
<Schema Namespace=""ODataDemo"" xmlns=""http://docs.oasis-open.org/odata/ns/edm"">
158+
<EntityContainer Name=""DefaultContainer"">
159+
<EntitySet Name=""Product"" EntityType=""Models.Product"" />
160+
</EntityContainer>
161+
</Schema>
162+
</edmx:DataServices>
163+
</edmx:Edmx>";
164+
}
165+
166+
167+
private string SqlTypeToDemType(string sqlType)
168+
{
169+
switch (sqlType)
170+
{
171+
case "bigint": return "Edm.Int64";
172+
case "binary": return "Edm.Byte[]";
173+
case "bit": return "Edm.Boolean";
174+
case "char": return "Edm.String";
175+
case "date": return "Edm.DateTime";
176+
case "datetime": return "Edm.DateTime";
177+
case "datetime2": return "Edm.DateTime";
178+
case "datetimeoffset": return "Edm.DateTimeOffset";
179+
case "decimal": return "Edm.Decimal";
180+
case "float": return "Edm.Double";
181+
case "image": return "Edm.Byte[]";
182+
case "int": return "Edm.Int32";
183+
case "money": return "Edm.Decimal";
184+
case "nchar": return "Edm.String";
185+
case "ntext": return "Edm.String";
186+
case "numeric": return "Edm.Decimal";
187+
case "nvarchar": return "Edm.String";
188+
case "real": return "Edm.Single";
189+
case "rowversion": return "Edm.Byte[]";
190+
case "smalldatetime": return "Edm.DateTime";
191+
case "smallint": return "Edm.Int16";
192+
case "smallmoney": return "Edm.Decimal";
193+
case "sql_variant": return "Edm.Object";
194+
case "text": return "Edm.String";
195+
case "time": return "Edm.TimeSpan";
196+
case "timestamp": return "Edm.Byte[]";
197+
case "tinyint": return "Edm.Byte";
198+
case "uniqueidentifier": return "Edm.Guid";
199+
case "varbinary": return "Edm.Byte[]";
200+
case "varchar": return "Edm.String";
201+
case "xml": return "Edm.Xml";
202+
default: throw new ArgumentException("Unsupported type", "sqlType");
203+
}
204+
}
205+
206+
private string ODataMetaData(TableSpec spec, string Namespace, string EntityName)
207+
{
208+
var metadata = new StringBuilder();
209+
metadata
210+
.AppendFormat(@"<?xml version=""1.0"" encoding=""utf-8""?>
211+
<edmx:Edmx Version=""4.0"" xmlns:edmx=""http://docs.oasis-open.org/odata/ns/edmx"">
212+
<edmx:DataServices>
213+
<Schema Namespace=""{0}"" xmlns=""http://docs.oasis-open.org/odata/ns/edm"">", Namespace)
214+
.AppendFormat(@"<EntityType Name=""{0}"">", EntityName);
215+
for(int i = 0; i< spec.columns.Count; i++)
216+
{
217+
if(i == 0)
218+
metadata.AppendFormat(@"<Key><PropertyRef Name=""{0}""/></Key>", spec.columns[0]);
219+
metadata.AppendFormat(@"<Property Name=""{0}"" Type=""{1}""/>", spec.columns[i], "Edm.Int32");
220+
}
221+
222+
metadata
223+
.AppendFormat(@"</EntityType>")
224+
//.Append("</Schema>")
225+
//.AppendFormat(@"<Schema Namespace=""{0}"" xmlns=""http://docs.oasis-open.org/odata/ns/edm"">")
226+
.AppendFormat(@"
227+
<EntityContainer Name=""{0}"">
228+
<EntitySet Name=""{1}"" EntityType=""{2}"" />
229+
</EntityContainer>
230+
</Schema>", "DefaultContainer", EntityName, "Models.Product")
231+
.AppendFormat(@"
232+
</edmx:DataServices>
233+
</edmx:Edmx>");
234+
235+
return metadata.ToString();
236+
}
237+
}
238+
}

samples/demos/ivs-people-register/Controllers/PeopleController.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ namespace Register.Controllers
1010
public class PeopleController : Controller
1111
{
1212
IQueryPipe pipe = null;
13-
TableSpec tableSpec = new TableSpec("dbo.People", "name,surname,address,town");
13+
TableSpec tableSpec = new TableSpec("dbo", "People", "name,surname,address,town");
1414

1515
public PeopleController(IQueryPipe sqlQueryService)
1616
{
@@ -36,6 +36,7 @@ public async Task GetAll()
3636
[HttpGet("odata")]
3737
public async Task OData()
3838
{
39+
Response.ContentType = "application/json";
3940
await this
4041
.ODataHandler(tableSpec, pipe)
4142
.Process();
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<Query Kind="Expression">
2+
<Connection>
3+
<ID>0a98b0bc-4850-40e5-9b82-0a5339b19c5f</ID>
4+
<Persist>true</Persist>
5+
<Driver Assembly="OData4DynamicDriver" PublicKeyToken="ac4f2d9e4b31c376">OData4.OData4DynamicDriver</Driver>
6+
<Server>http://localhost:59934/api/odata</Server>
7+
</Connection>
8+
</Query>
9+
10+
People
11+
.Where(p=>p.id<50 && p.id>5)
12+
.OrderBy(p=>p.town)
13+
.Select(p=>new {p.id,p.name,p.town})

samples/demos/ivs-people-register/project.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"Microsoft.Extensions.Logging.Console": "1.0.0",
1717
"Microsoft.Extensions.Logging.Debug": "1.0.0",
1818
"Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0",
19-
"Sql-Server-Rest-Api": "0.2.7"
19+
"Sql-Server-Rest-Api": "0.3"
2020
},
2121

2222
"tools": {

samples/demos/ivs-people-register/sql-scripts/1 setup.sql

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
CREATE TABLE dbo.People(
1+
DROP TABLE IF EXISTS dbo.People
2+
GO
3+
CREATE TABLE dbo.People(
24
id int primary key identity,
35
name nvarchar(50),
46
surname nvarchar(50),
@@ -10,10 +12,11 @@ GO
1012
alter database current set compatibility_level = 130;
1113
go
1214

15+
--select name, surname, address, town from dbo.People for json path
1316
declare @people nvarchar(max) =
14-
N'[{"name":"渡邉󠄐","surname":"","address":"神奈川県藤沢市辻堂1-1-41","town":"辻堂"},{"name":"渡邉󠄑","surname":"龍󠄄之介","address":"神奈川県藤沢市辻󠄀堂1-503","town":"辻󠄀堂"},{"name":"渡邉󠄒","surname":"博美","address":"兵庫県芦屋市精道町7番6号","town":"芦屋"},{"name":"田辺","surname":"浩一","address":"東京都港区港南2-16-3","town":"港南"},{"name":"田辺󠄁","surname":"洋子","address":"鹿児島県薩摩川内市神田町3番22号","town":"薩摩"},{"name":"田辺󠄂","surname":"大輔","address":"愛知県名古屋市熱田区川並町2-1","town":"川並"},{"name":"斎藤","surname":"由紀","address":"滋賀県東近江市五個荘川並󠄂町1-1","town":"川並󠄂"},{"name":"齋󠄂藤","surname":"俊󠄁","address":"東京都葛󠄀飾区小岩1-1-1","town":"葛󠄀飾"},{"name":"齋󠄃藤","surname":"龍一","address":"岡山県備前市東片上126番地 ","town":"芦󠄆別市"},{"name":"龍地","surname":"花子","address":"茨城県水戸市備󠄁前町816-2","town":"芦󠄂別市"},{"name":"龍󠄃地","surname":"次郎","address":"奈良県天理市備󠄂前町2-2-2","town":"芦別市"},{"name":"","surname":"龍󠄅二","address":"兵庫県芦󠄀屋市精道町7番6号","town":"芦󠄂屋"}]';
17+
N'[{"name":"","surname":"渡邉󠄐","address":"神奈川県藤沢市辻堂1-1-41","town":"辻堂"},{"name":"龍󠄄之介","surname":"渡邉󠄑","address":"神奈川県藤沢市辻󠄀堂1-503","town":"辻󠄀堂"},{"name":"博美","surname":"渡邉󠄒","address":"兵庫県芦屋市精道町7番6号","town":"芦屋"},{"name":"浩一","surname":"田辺","address":"東京都港区港南2-16-3","town":"港南"},{"name":"洋子","surname":"田辺󠄁","address":"鹿児島県薩摩川内市神田町3番22号","town":"薩摩"},{"name":"大輔","surname":"田辺󠄂","address":"愛知県名古屋市熱田区川並町2-1","town":"川並"},{"name":"由紀","surname":"斎藤","address":"滋賀県東近江市五個荘川並󠄂町1-1","town":"川並󠄂"},{"name":"俊󠄁","surname":"齋󠄂藤","address":"東京都葛󠄀飾区小岩1-1-1","town":"葛󠄀飾"},{"name":"龍一","surname":"齋󠄃藤","address":"岡山県備前市東片上126番地 ","town":"芦󠄆別市"},{"name":"花子","surname":"龍地","address":"茨城県水戸市備󠄁前町816-2","town":"芦󠄂別市"},{"name":"次郎","surname":"龍󠄃地","address":"奈良県天理市備󠄂前町2-2-2","town":"芦別市"},{"name":"龍󠄅二","surname":"","address":"兵庫県芦󠄀屋市精道町7番6号","town":"芦󠄂屋"}]';
1518

1619
insert into people (name, surname, address, town)
17-
select rtrim(name), surname, address, town
20+
select name, surname, address, town
1821
from openjson(@people)
1922
with (name nvarchar(50),surname nvarchar(50),address nvarchar(200),town nvarchar(50))

0 commit comments

Comments
 (0)