Merge remote-tracking branch 'refs/remotes/origin/master' into jodebrui
This commit is contained in:
Коммит
ea783d13b2
|
@ -0,0 +1,60 @@
|
|||
# Connect to MSSQL using the Microsoft ODBC Driver on Linux
|
||||
|
||||
|
||||
[C code sample] (sample_c_linux.c) that runs on Linux. The sample connects to MSSQL (SQL Server, Azure SQL DB, Azure SQL DW) using the Microsoft ODBC Driver for Linux.
|
||||
|
||||
|
||||
## Prerequisites
|
||||
|
||||
|
||||
Open your terminal and install the Microsoft ODBC Driver on your machine
|
||||
|
||||
Install the ODBC Driver for Linux on Ubuntu 15.10:
|
||||
|
||||
sudo su
|
||||
sudo sh -c 'echo "deb [arch=amd64] https://apt-mo.trafficmanager.net/repos/mssql-ubuntu-preview/ wily main" > /etc/apt/sources.list.d/mssqlpreview.list'
|
||||
sudo apt-key adv --keyserver apt-mo.trafficmanager.net --recv-keys 417A0893
|
||||
sudo apt-get update
|
||||
sudo apt-get install msodbcsql
|
||||
sudo apt-get install unixodbc-dev-utf16 (this step is optional but recommended)
|
||||
|
||||
Install the ODBC Driver for Linux on Ubuntu 16.04
|
||||
|
||||
sudo su
|
||||
sudo sh -c 'echo "deb [arch=amd64] https://apt-mo.trafficmanager.net/repos/mssql-ubuntu-preview/ xenial main" > /etc/apt/sources.list.d/mssqlpreview.list'
|
||||
sudo apt-key adv --keyserver apt-mo.trafficmanager.net --recv-keys 417A0893
|
||||
sudo apt-get update
|
||||
sudo apt-get install msodbcsql
|
||||
sudo apt-get install unixodbc-dev-utf16 (this step is optional but recommended)
|
||||
|
||||
Install the ODBC Driver for Linux on RedHat 6
|
||||
|
||||
sudo su
|
||||
yum-config-manager --add-repo https://apt-mo.trafficmanager.net/yumrepos/mssql-rhel6-preview/
|
||||
yum-config-manager --enable mssql-rhel6-preview
|
||||
wget "http://aka.ms/msodbcrhelpublickey/dpgswdist.v1.asc"
|
||||
rpm --import dpgswdist.v1.asc
|
||||
yum remove unixodbc (to avoid conflicts during installation)
|
||||
yum update
|
||||
yum install msodbcsql
|
||||
yum install unixODBC-utf16-devel (this step is optional but recommended)
|
||||
|
||||
Install the ODBC Driver for Linux on RedHat 7
|
||||
|
||||
sudo su
|
||||
yum-config-manager --add-repo https://apt-mo.trafficmanager.net/yumrepos/mssql-rhel7-preview/
|
||||
yum-config-manager --enable mssql-rhel7-preview
|
||||
wget "http://aka.ms/msodbcrhelpublickey/dpgswdist.v1.asc"
|
||||
rpm --import dpgswdist.v1.asc
|
||||
yum remove unixodbc (to avoid conflicts during installation)
|
||||
yum update
|
||||
yum install msodbcsql
|
||||
yum install unixODBC-utf16-devel (this step is optional but recommended)
|
||||
|
||||
|
||||
After your machine is configured with the ODBC Driver change the credentials in the C sample, compile it and then run it:
|
||||
|
||||
gcc sample_c_linux.c -o sample_c_linux -lodbc -w
|
||||
./sample_c_linux
|
||||
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sql.h>
|
||||
#include <sqlext.h>
|
||||
#include <string.h>
|
||||
|
||||
#define RESULT_LEN 256
|
||||
|
||||
#define CHECK_ERROR(e, s, h, t) ({\
|
||||
if (e!=SQL_SUCCESS && e != SQL_SUCCESS_WITH_INFO) {extract_error(s, h, t); goto exit;} \
|
||||
})
|
||||
void extract_error(char *fn, SQLHANDLE handle, SQLSMALLINT type)
|
||||
{
|
||||
SQLINTEGER i = 0;
|
||||
SQLINTEGER NativeError;
|
||||
SQLCHAR SQLState[ 7 ];
|
||||
SQLCHAR MessageText[256];
|
||||
SQLSMALLINT TextLength;
|
||||
SQLRETURN ret;
|
||||
|
||||
fprintf(stderr, "\nThe driver reported the following error %s\n", fn);
|
||||
do
|
||||
{
|
||||
ret = SQLGetDiagRec(type, handle, ++i, SQLState, &NativeError,
|
||||
MessageText, sizeof(MessageText), &TextLength);
|
||||
if (SQL_SUCCEEDED(ret)) {
|
||||
printf("%s:%ld:%ld:%s\n",
|
||||
SQLState, (long) i, (long) NativeError, MessageText);
|
||||
}
|
||||
}
|
||||
while( ret == SQL_SUCCESS );
|
||||
}
|
||||
int main () {
|
||||
|
||||
SQLHENV henv = SQL_NULL_HENV; // Environment
|
||||
SQLHDBC hdbc = SQL_NULL_HDBC; // Connection handle
|
||||
SQLHSTMT hstmt = SQL_NULL_HSTMT; // Statement handle
|
||||
SQLRETURN retcode;
|
||||
SQLCHAR strResult[RESULT_LEN];
|
||||
SQLCHAR outstr[1024];
|
||||
SQLSMALLINT outstrlen;
|
||||
int i=0;
|
||||
// Allocate environment handle
|
||||
retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
|
||||
CHECK_ERROR(retcode, "SQLAllocHandle(SQL_HANDLE_ENV)",
|
||||
henv, SQL_HANDLE_ENV);
|
||||
// Set the ODBC version environment attribute
|
||||
retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION,
|
||||
(SQLPOINTER*)SQL_OV_ODBC3, 0);
|
||||
CHECK_ERROR(retcode, "SQLSetEnvAttr(SQL_ATTR_ODBC_VERSION)",
|
||||
henv, SQL_HANDLE_ENV);
|
||||
// Allocate connection handle
|
||||
retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
|
||||
CHECK_ERROR(retcode, "SQLAllocHandle(SQL_HANDLE_DBC)",
|
||||
hdbc, SQL_HANDLE_DBC);
|
||||
// Set login timeout to 5 seconds
|
||||
SQLSetConnectAttr(hdbc, SQL_LOGIN_TIMEOUT, (SQLPOINTER)5, 0);
|
||||
CHECK_ERROR(retcode, "SQLSetConnectAttr(SQL_LOGIN_TIMEOUT)",
|
||||
hdbc, SQL_HANDLE_DBC);
|
||||
// Connect to data source
|
||||
retcode = SQLDriverConnect(hdbc, NULL, "Driver=ODBC Driver 13 for SQL Server;Server=<yourserver>;Uid=<yourusername>;Pwd=<yourpassword>;database=<yourdatabase>", SQL_NTS, outstr, sizeof(outstr), &outstrlen, SQL_DRIVER_NOPROMPT);
|
||||
// Allocate statement handle
|
||||
retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
|
||||
CHECK_ERROR(retcode, "SQLAllocHandle(SQL_HANDLE_STMT)",
|
||||
hstmt, SQL_HANDLE_STMT);
|
||||
retcode = SQLExecDirect(hstmt,
|
||||
(SQLCHAR*) "SELECT @@Version", SQL_NTS);
|
||||
CHECK_ERROR(retcode, "SQLExecDirect()", hstmt, SQL_HANDLE_STMT);
|
||||
|
||||
// Bind columns
|
||||
|
||||
retcode = SQLBindCol(hstmt, 1, SQL_C_CHAR, &strResult, RESULT_LEN, 0);
|
||||
|
||||
|
||||
// Fetch and print each row of data until SQL_NO_DATA returned.
|
||||
for (i=0; ; i++) {
|
||||
retcode = SQLFetch(hstmt);
|
||||
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
|
||||
printf("Result is: %s", strResult);
|
||||
} else {
|
||||
if (retcode != SQL_NO_DATA) {
|
||||
CHECK_ERROR(retcode, "SQLFetch()", hstmt, SQL_HANDLE_STMT);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
|
||||
printf ("\nComplete.\n");
|
||||
// Free handles
|
||||
// Statement
|
||||
if (hstmt != SQL_NULL_HSTMT)
|
||||
SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
|
||||
// Connection
|
||||
if (hdbc != SQL_NULL_HDBC) {
|
||||
SQLDisconnect(hdbc);
|
||||
SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
|
||||
}
|
||||
// Environment
|
||||
if (henv != SQL_NULL_HENV)
|
||||
SQLFreeHandle(SQL_HANDLE_ENV, henv);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
This is a repository of all demos used at conferences and webinars.
|
|
@ -0,0 +1,2 @@
|
|||
<h1>MSSQLTIGER Demos</h1>
|
||||
This is a repository of the scripts used during demos that are delivered by the SQL Server Tiger team.
|
|
@ -0,0 +1,8 @@
|
|||
|
||||
# CheckClientUpdates.ps1
|
||||
The PowerShell Script currently supports the following:
|
||||
* Check if SQL Server Native Client can support TLS 1.2
|
||||
* Check if Microsoft ODBC Driver for SQL Server can support TLS 1.2
|
||||
This script is restricted to work on x64 and x86 platforms
|
||||
|
||||
More details about TLS 1.2 support for SQL Server can be found on [KB3135244] (https://support.microsoft.com/en-us/kb/3135244)
|
|
@ -0,0 +1,56 @@
|
|||
# Helper functions to check if TLS 1.2 updates are required
|
||||
# Script currently supports checking for the following:
|
||||
# a. Check if SQL Server Native Client can support TLS 1.2
|
||||
# b. Check if Microsoft ODBC Driver for SQL Server can support TLS 1.2
|
||||
# This script is restricted to work on x64 and x86 platforms
|
||||
Function Check-Sqlncli()
|
||||
{
|
||||
# Fetch the different Native Client installations found on the machine
|
||||
$sqlncli = Get-WmiObject -Class Win32_Product | Where-Object {$_.Name -like "*Native Client*"} | Select Name,Version
|
||||
# Check and report if an update is required for each entry found
|
||||
foreach ($cli in $sqlncli)
|
||||
{
|
||||
# SQL Server 2012 and 2014
|
||||
if ($cli.Version.Split(".")[2] -lt 6538 -and $cli.Version.Split(".")[0] -eq 11)
|
||||
{
|
||||
Write-Host $cli.Name "with version" $cli.Version " needs to be updated to use TLS 1.2" -ForegroundColor Red
|
||||
}
|
||||
# SQL Server 2008
|
||||
elseif ($cli.Version.Split(".")[2] -lt 6543 -and $cli.Version.Split(".")[1] -eq 0 -and $cli.Version.Split(".")[0] -eq 10)
|
||||
{
|
||||
Write-Host $cli.Name "with version" $cli.Version " needs to be updated to use TLS 1.2" -ForegroundColor Red
|
||||
}
|
||||
# SQL Server 2008 R2
|
||||
elseif ($cli.Version.Split(".")[2] -lt 6537 -and $cli.Version.Split(".")[1] -eq 50 -and $cli.Version.Split(".")[0] -eq 10)
|
||||
{
|
||||
Write-Host $cli.Name "with version" $cli.Version " needs to be updated to use TLS 1.2" -ForegroundColor Red
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Host $cli.Name "with version" $cli.Version " supports TLS 1.2" -ForegroundColor Green
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Function Check-SqlODBC()
|
||||
{
|
||||
# Fetch the different MS SQL ODBC installations found on the machine
|
||||
$sqlodbc = Get-WmiObject -Class Win32_Product | Where-Object {$_.Name -like "*ODBC*"} | Select Name,Version
|
||||
# Check and report if an update is required for each entry found
|
||||
foreach ($cli in $sqlodbc)
|
||||
{
|
||||
# SQL Server 2012 and 2014
|
||||
if ($cli.Version.Split(".")[2] -lt 4219 -and $cli.Version.Split(".")[0] -eq 12)
|
||||
{
|
||||
Write-Host $cli.Name "with version" $cli.Version " needs to be updated to use TLS 1.2" -ForegroundColor Red
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Host $cli.Name "with version" $cli.Version " supports TLS 1.2" -ForegroundColor Green
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Call the functions
|
||||
Check-Sqlncli
|
||||
Check-SqlODBC
|
|
@ -18,21 +18,25 @@ Sample order processing workload that can be used for benchmarking transactional
|
|||
1. Create the database, tables, and stored procedures using the T-SQL scripts in the corresponding subfolders.
|
||||
|
||||
- The hash indexes are sized for large databases, processing billions of orders. They are appropriate for 1TB and larger database size. For smaller database and memory size, adjust the bucket counts accordingly.
|
||||
- There are plans to publish scripts for initial populate of the tables. Timeline is TBD.
|
||||
- Scripts are also provided for corresponding disk-based tables and traditional stored procedures, to compare performance between disk-based and memory-optimized tables.
|
||||
|
||||
2. Run the stored procedures using the following mix.
|
||||
|
||||
- There are plans to make a scalable workload driver available as well. Timeline is TBD.
|
||||
|
||||
|Stored Procedure|Weight|Distribution|
|
||||
|----------|--------|-------|
|
||||
|GetOrdersByCustomerID|8|25.8%|
|
||||
|GetProductsByType|6|19.4%|
|
||||
|GetProductsPriceByPK |4 |12.9%|
|
||||
|ProductSelectionCriteria |2 |6.5%|
|
||||
|InsertOrder |10 |32.3%|
|
||||
|FulfillOrders |1 |3.2%|
|
||||
|
||||
|Stored Procedure|Weight|
|
||||
|----------|--------|
|
||||
|GetOrdersByCustomerID|8|
|
||||
|GetProductsByType|6|
|
||||
|GetProductsPriceByPK |4 |
|
||||
|ProductSelectionCriteria |2 |
|
||||
|InsertOrder |10 |
|
||||
|FulfillOrders |1 |
|
||||
|
||||
The recommendation is to use two different drivers:
|
||||
a. Main order processing driver, that is multi-threaded (e.g., 100 or 200 clients), and runs the procedures, GetOrdersByCustomerID, GetProductsByType, GetProductsPriceByPK, ProductSelectionCriteria, and InsertOrder.
|
||||
a. Fulfullment driver, which runs the procedure FulfillOrders. This driver should have a single client to avoid conflicts.
|
||||
|
||||
## Workload description
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
-- need to use the WITH (SNAPSHOT) hint for ad hoc queries accessing memory-optimized
|
||||
-- tables.
|
||||
--
|
||||
-- Applies To: SQL Server 2014 (or higher); Azure SQL Database
|
||||
-- Applies To: SQL Server 2016 (or higher); Azure SQL Database
|
||||
-- Author: Jos de Bruijn (Microsoft)
|
||||
-- Last Updated: 2016-05-02
|
||||
|
||||
|
|
|
@ -41,8 +41,8 @@ This Windows Forms sample application built on .NET Framework 4.6 demonstrates
|
|||
8. Start the workload with the **Start** button, and run for a while to show perf profile. Then press stop to stop the workload. You can tweak aspects of the workload (e.g., rows per transaction) through the configuration form accessed using the "Options" menue.
|
||||
|
||||
9. In the database project,
|
||||
- Change TicketReservations.sql to a memory-optimized table (instructions commented in the file itself)
|
||||
- Change InsertTicketReservations.sql to natively compiled (instructions in the same file)
|
||||
- Change TicketReservationDetail.sql to a memory-optimized table (instructions commented in the file itself)
|
||||
- Change InsertReservationDetails.sql to natively compiled (instructions in the same file)
|
||||
|
||||
10. Publish the database project to the same database – the tool will take care of making the necessary changes.
|
||||
Note that, as part of publication, the data is copied from the old disk-based table to the new memory-optimized table, so the longer you run the initial workload, the longer this publication takes. To speed up the process you can run `TRUNCATE TABLE dbo.TicketReservationDetail` in the database.
|
||||
|
|
|
@ -1,4 +1,11 @@
|
|||
|
||||
create proc Demo_Reset
|
||||
as
|
||||
TRUNCATE TABLE dbo.TicketReservationDetail;
|
||||
DECLARE @isMemoryTable BIT
|
||||
|
||||
SELECT @isMemoryTable = is_memory_optimized FROM sys.tables
|
||||
WHERE [name] = 'TicketReservationDetail'
|
||||
|
||||
IF(@isMemoryTable= 1) DELETE dbo.TicketReservationDetail
|
||||
ELSE TRUNCATE TABLE dbo.TicketReservationDetail;
|
||||
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
*.xproj.user
|
||||
.vs/*
|
||||
.vscode/*
|
||||
bin/*
|
||||
obj/*
|
||||
*.sln
|
||||
*.log
|
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>c8014cba-1952-414a-b78e-f60f9e5c5625</ProjectGuid>
|
||||
<RootNamespace>CommentsApp</RootNamespace>
|
||||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
|
||||
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
|
||||
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\DotNet.Web\Microsoft.DotNet.Web.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
|
@ -0,0 +1,39 @@
|
|||
using Belgrade.SqlClient;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Data.SqlClient;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CommentApp.Controllers
|
||||
{
|
||||
[Route("api/[controller]")]
|
||||
public class commentsController : Controller
|
||||
{
|
||||
private readonly IQueryPipe SqlPipe;
|
||||
private readonly ICommand SqlCommand;
|
||||
|
||||
public commentsController(ICommand sqlCommand, IQueryPipe sqlPipe)
|
||||
{
|
||||
this.SqlCommand = sqlCommand;
|
||||
this.SqlPipe = sqlPipe;
|
||||
}
|
||||
|
||||
// GET api/comment
|
||||
[HttpGet]
|
||||
public async Task Get()
|
||||
{
|
||||
await SqlPipe.Stream("select * from Comments FOR JSON PATH", Response.Body, "[]");
|
||||
}
|
||||
|
||||
// POST api/comment
|
||||
[HttpPost]
|
||||
public async Task Post(string author, string text)
|
||||
{
|
||||
string comment = new StreamReader(Request.Body).ReadToEnd();
|
||||
var cmd = new SqlCommand( "insert into Comments values (@author, @text)");
|
||||
cmd.Parameters.AddWithValue("author", author);
|
||||
cmd.Parameters.AddWithValue("text", text);
|
||||
await SqlCommand.ExecuteNonQuery(cmd);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
|
||||
namespace TodoApp
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
var host = new WebHostBuilder()
|
||||
.UseKestrel()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseIISIntegration()
|
||||
.UseStartup<Startup>()
|
||||
.Build();
|
||||
|
||||
host.Run();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:15194/",
|
||||
"sslPort": 0
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "index.html",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"CommentApp": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "http://localhost:5001/index.html",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
# ASP.NET Core REST Web API that uses SQL/JSON functionalities
|
||||
|
||||
This project contains an implementation of ASP.NET Core REST API backend for [ReactJS Comments tutorial](https://facebook.github.io/react/docs/tutorial.html).
|
||||
In this example you will see how easily you can integrate Single-page apps implemented using ReactJS with SQL Server 2016 or Azure SQL Database using ASP.NET Core and JSON functions that are available in SQL Server 2016.
|
||||
|
||||
### Contents
|
||||
|
||||
[About this sample](#about-this-sample)<br/>
|
||||
[Before you begin](#before-you-begin)<br/>
|
||||
[Run this sample](#run-this-sample)<br/>
|
||||
[Sample details](#sample-details)<br/>
|
||||
[Disclaimers](#disclaimers)<br/>
|
||||
[Related links](#related-links)<br/>
|
||||
|
||||
<a name=about-this-sample></a>
|
||||
|
||||
## About this sample
|
||||
|
||||
- **Applies to:** SQL Server 2016 (or higher), Azure SQL Database
|
||||
- **Key features:** FOR JSON clause in SQL Server 2016/Azure SQL Database.
|
||||
- **Programming Language:** JavaScript/ReactJS, C#, Transact-SQL
|
||||
- **Authors:** Jovan Popovic
|
||||
|
||||
<a name=before-you-begin></a>
|
||||
|
||||
## Before you begin
|
||||
|
||||
To run this sample, you need the following prerequisites.
|
||||
|
||||
**Software prerequisites:**
|
||||
|
||||
1. SQL Server 2016 (or higher) or an Azure SQL Database
|
||||
2. Visual Studio 2015 Update 3 (or higher) or Visual Studio Code Editor with the ASP.NET Core 1.0 (or higher)
|
||||
|
||||
**Azure prerequisites:**
|
||||
|
||||
1. Permission to create an Azure SQL Database
|
||||
|
||||
<a name=run-this-sample></a>
|
||||
|
||||
## Run this sample
|
||||
|
||||
1. Create a database on SQL Server 2016 or Azure SQL Database.
|
||||
|
||||
2. From SQL Server Management Studio or Sql Server Data Tools connect to your SQL Server 2016 or Azure SQL database and execute [sql-scripts/setup.sql](sql-scripts/setup.sql) script that will create and populate Comments table.
|
||||
|
||||
3. From Visual Studio 2015, open the **CommentsReactApp.xproj** file from the root directory. Restore packages using right-click menu on the project in Visual Studio and by choosing Restore Packages item. As an alternative, you may run **dotnet restore** from the command line (from the root folder of application).
|
||||
|
||||
4. Locate Startup.cs file in the project, change connection string in ConfigureServices() method to reference your database (default value CommentsDb database on local instance with integrated security), and build solution using Ctrl+Shift+B, right-click on project + Build, Build/Build Solution from menu, or **dotnet build** command from the command line (from the root folder of application).
|
||||
|
||||
5. Run the sample app using F5 or Ctrl+F5 in Visual Studio 2015, or using **dotnet run** executed in the command prompt of the project root folder.
|
||||
1. Open /index.html Url to get all comments from database,
|
||||
2. Add new comment using the form below the list of comments.
|
||||
|
||||
<a name=sample-details></a>
|
||||
|
||||
## Sample details
|
||||
|
||||
This sample application shows how to create REST API service is used as beckend for ReactJS app.
|
||||
Front-end code stored in wwwroot folder is **unmodified** Facebook's [ReactJS sample comments app](https://facebook.github.io/react/docs/tutorial.html).
|
||||
ASP.NET Core Web API is used to implement REST Service called by Comments front-end app.
|
||||
Service uses FOR JSON clause that is available in SQL Server 2016 and Azure SQL Database.
|
||||
|
||||
<a name=disclaimers></a>
|
||||
|
||||
## Disclaimers
|
||||
The code included in this sample is not intended demonstrate some general guidance and architectural patterns for web development. It contains minimal code required to create REST API, and it does not use some patterns such as Repository. Sample uses built-in ASP.NET Core Dependency Injection mechanism; however, this is not prerequisite.
|
||||
You can easily modify this code to fit the architecture of your application.
|
||||
|
||||
<a name=related-links></a>
|
||||
|
||||
## Related Links
|
||||
|
||||
You can find more information about the components that are used in this sample on these locations:
|
||||
- [ASP.NET Core](http://www.asp.net/core).
|
||||
- [JSON Support in Sql Server](https://msdn.microsoft.com/en-us/library/dn921897.aspx).
|
||||
- [ReactJS](https://facebook.github.io/react/).
|
||||
- [JQuery](https://jquery.com/).
|
||||
|
||||
## Code of Conduct
|
||||
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
|
||||
|
||||
## License
|
||||
These samples and templates are all licensed under the MIT license. See the license.txt file in the root.
|
||||
|
||||
## Questions
|
||||
Email questions to: [sqlserversamples@microsoft.com](mailto: sqlserversamples@microsoft.com).
|
|
@ -0,0 +1,49 @@
|
|||
using Belgrade.SqlClient;
|
||||
using Belgrade.SqlClient.SqlDb;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Data.SqlClient;
|
||||
|
||||
namespace TodoApp
|
||||
{
|
||||
public class Startup
|
||||
{
|
||||
public Startup(IHostingEnvironment env)
|
||||
{
|
||||
var builder = new ConfigurationBuilder()
|
||||
.SetBasePath(env.ContentRootPath)
|
||||
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
|
||||
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
|
||||
.AddEnvironmentVariables();
|
||||
Configuration = builder.Build();
|
||||
}
|
||||
|
||||
public IConfigurationRoot Configuration { get; }
|
||||
|
||||
// This method gets called by the runtime. Use this method to add services to the container.
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
//const string ConnString = "Server=SERVERNAME.database.windows.net;Database=DATABASENAME;User Id=USERNAME;Password=PASSWORD";
|
||||
const string ConnString = "Server=.;Database=CommentsDb;Integrated Security=true";
|
||||
services.AddTransient<IQueryPipe>( _=> new QueryPipe(new SqlConnection(ConnString)));
|
||||
services.AddTransient<ICommand>( _=> new Command(new SqlConnection(ConnString)));
|
||||
|
||||
// Add framework services.
|
||||
services.AddMvc();
|
||||
|
||||
}
|
||||
|
||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
|
||||
{
|
||||
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
|
||||
loggerFactory.AddDebug();
|
||||
|
||||
app.UseMvc();
|
||||
app.UseStaticFiles();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"Logging": {
|
||||
"IncludeScopes": false,
|
||||
"LogLevel": {
|
||||
"Default": "Debug",
|
||||
"System": "Information",
|
||||
"Microsoft": "Information"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
{
|
||||
"dependencies": {
|
||||
"Belgrade.Sql.Client": "0.3.0",
|
||||
"Microsoft.AspNetCore.Mvc": "1.0.0",
|
||||
"Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
|
||||
"Microsoft.AspNetCore.Server.Kestrel": "1.0.0",
|
||||
"Microsoft.AspNetCore.StaticFiles": "1.0.0",
|
||||
"Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0",
|
||||
"Microsoft.Extensions.Configuration.FileExtensions": "1.0.0",
|
||||
"Microsoft.Extensions.Configuration.Json": "1.0.0",
|
||||
"Microsoft.Extensions.Logging": "1.0.0",
|
||||
"Microsoft.Extensions.Logging.Console": "1.0.0",
|
||||
"Microsoft.Extensions.Logging.Debug": "1.0.0",
|
||||
"System.Data.SqlClient": "4.1.0"
|
||||
},
|
||||
|
||||
"tools": {
|
||||
"Microsoft.AspNetCore.Server.IISIntegration.Tools": {
|
||||
"version": "1.0.0-preview1-final",
|
||||
"imports": "portable-net45+win8+dnxcore50"
|
||||
}
|
||||
},
|
||||
|
||||
"frameworks": {
|
||||
"netcoreapp1.0": {
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.App": {
|
||||
"version": "1.0.0",
|
||||
"type": "platform"
|
||||
}
|
||||
}
|
||||
},
|
||||
"net46": {}
|
||||
},
|
||||
|
||||
"buildOptions": {
|
||||
"emitEntryPoint": true,
|
||||
"preserveCompilationContext": true
|
||||
},
|
||||
|
||||
"publishOptions": {
|
||||
"include": [
|
||||
"wwwroot",
|
||||
"Views",
|
||||
"appsettings.json",
|
||||
"web.config"
|
||||
]
|
||||
},
|
||||
|
||||
"scripts": {
|
||||
"postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]
|
||||
}
|
||||
}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,14 @@
|
|||
DROP TABLE IF EXISTS Comments
|
||||
GO
|
||||
|
||||
CREATE TABLE Comments (
|
||||
id int IDENTITY PRIMARY KEY,
|
||||
author nvarchar(30) NOT NULL,
|
||||
text nvarchar(4000)
|
||||
)
|
||||
GO
|
||||
|
||||
INSERT INTO Comments (author, text)
|
||||
VALUES
|
||||
('John','This is great!'),
|
||||
('Jane','I like the fact that it is simple.')
|
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
|
||||
<!--
|
||||
Configure your application settings in appsettings.json. Learn more at http://go.microsoft.com/fwlink/?LinkId=786380
|
||||
-->
|
||||
|
||||
<system.webServer>
|
||||
<handlers>
|
||||
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified"/>
|
||||
</handlers>
|
||||
<aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="false"/>
|
||||
</system.webServer>
|
||||
</configuration>
|
|
@ -0,0 +1,59 @@
|
|||
body {
|
||||
background: #fff;
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
font-size: 15px;
|
||||
line-height: 1.7;
|
||||
margin: 0;
|
||||
padding: 30px;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #4183c4;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
code {
|
||||
background-color: #f8f8f8;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 3px;
|
||||
font-family: "Bitstream Vera Sans Mono", Consolas, Courier, monospace;
|
||||
font-size: 12px;
|
||||
margin: 0 2px;
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4 {
|
||||
font-weight: bold;
|
||||
margin: 0 0 15px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
h1 {
|
||||
border-bottom: 1px solid #ddd;
|
||||
font-size: 2.5em;
|
||||
}
|
||||
|
||||
h2 {
|
||||
border-bottom: 1px solid #eee;
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
p, ul {
|
||||
margin: 15px 0;
|
||||
}
|
||||
|
||||
ul {
|
||||
padding-left: 30px;
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>React Tutorial</title>
|
||||
<!-- Not present in the tutorial. Just for basic styling. -->
|
||||
<link rel="stylesheet" href="css/base.css" />
|
||||
<script src="https://npmcdn.com/react@15.3.0/dist/react.js"></script>
|
||||
<script src="https://npmcdn.com/react-dom@15.3.0/dist/react-dom.js"></script>
|
||||
<script src="https://npmcdn.com/babel-core@5.8.38/browser.min.js"></script>
|
||||
<script src="https://npmcdn.com/jquery@3.1.0/dist/jquery.min.js"></script>
|
||||
<script src="https://npmcdn.com/remarkable@1.6.2/dist/remarkable.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="content"></div>
|
||||
<script type="text/babel" src="scripts/example.js"></script>
|
||||
<script type="text/babel">
|
||||
// To get started with this tutorial running your own code, simply remove
|
||||
// the script tag loading scripts/example.js and start writing code here.
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,147 @@
|
|||
/**
|
||||
* This file provided by Facebook is for non-commercial testing and evaluation
|
||||
* purposes only. Facebook reserves all rights not expressly granted.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
var Comment = React.createClass({
|
||||
rawMarkup: function() {
|
||||
var md = new Remarkable();
|
||||
var rawMarkup = md.render(this.props.children.toString());
|
||||
return { __html: rawMarkup };
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<div className="comment">
|
||||
<h2 className="commentAuthor">
|
||||
{this.props.author}
|
||||
</h2>
|
||||
<span dangerouslySetInnerHTML={this.rawMarkup()} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var CommentBox = React.createClass({
|
||||
loadCommentsFromServer: function() {
|
||||
$.ajax({
|
||||
url: this.props.url,
|
||||
dataType: 'json',
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
this.setState({data: data});
|
||||
}.bind(this),
|
||||
error: function(xhr, status, err) {
|
||||
console.error(this.props.url, status, err.toString());
|
||||
}.bind(this)
|
||||
});
|
||||
},
|
||||
handleCommentSubmit: function(comment) {
|
||||
var comments = this.state.data;
|
||||
// Optimistically set an id on the new comment. It will be replaced by an
|
||||
// id generated by the server. In a production application you would likely
|
||||
// not use Date.now() for this and would have a more robust system in place.
|
||||
comment.id = Date.now();
|
||||
var newComments = comments.concat([comment]);
|
||||
this.setState({data: newComments});
|
||||
$.ajax({
|
||||
url: this.props.url,
|
||||
dataType: 'json',
|
||||
type: 'POST',
|
||||
data: comment,
|
||||
success: function(data) {
|
||||
this.setState({data: data});
|
||||
}.bind(this),
|
||||
error: function(xhr, status, err) {
|
||||
this.setState({data: comments});
|
||||
console.error(this.props.url, status, err.toString());
|
||||
}.bind(this)
|
||||
});
|
||||
},
|
||||
getInitialState: function() {
|
||||
return {data: []};
|
||||
},
|
||||
componentDidMount: function() {
|
||||
this.loadCommentsFromServer();
|
||||
setInterval(this.loadCommentsFromServer, this.props.pollInterval);
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<div className="commentBox">
|
||||
<h1>Comments</h1>
|
||||
<CommentList data={this.state.data} />
|
||||
<CommentForm onCommentSubmit={this.handleCommentSubmit} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var CommentList = React.createClass({
|
||||
render: function() {
|
||||
var commentNodes = this.props.data.map(function(comment) {
|
||||
return (
|
||||
<Comment author={comment.author} key={comment.id}>
|
||||
{comment.text}
|
||||
</Comment>
|
||||
);
|
||||
});
|
||||
return (
|
||||
<div className="commentList">
|
||||
{commentNodes}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var CommentForm = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {author: '', text: ''};
|
||||
},
|
||||
handleAuthorChange: function(e) {
|
||||
this.setState({author: e.target.value});
|
||||
},
|
||||
handleTextChange: function(e) {
|
||||
this.setState({text: e.target.value});
|
||||
},
|
||||
handleSubmit: function(e) {
|
||||
e.preventDefault();
|
||||
var author = this.state.author.trim();
|
||||
var text = this.state.text.trim();
|
||||
if (!text || !author) {
|
||||
return;
|
||||
}
|
||||
this.props.onCommentSubmit({author: author, text: text});
|
||||
this.setState({author: '', text: ''});
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<form className="commentForm" onSubmit={this.handleSubmit}>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Your name"
|
||||
value={this.state.author}
|
||||
onChange={this.handleAuthorChange}
|
||||
/>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Say something..."
|
||||
value={this.state.text}
|
||||
onChange={this.handleTextChange}
|
||||
/>
|
||||
<input type="submit" value="Post" />
|
||||
</form>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
ReactDOM.render(
|
||||
<CommentBox url="/api/comments" pollInterval={2000} />,
|
||||
document.getElementById('content')
|
||||
);
|
|
@ -14,4 +14,8 @@ This project contains an example implementation of ASP.NET Core REST API with CR
|
|||
|
||||
[Product Catalog Web app - ASP.NET Core/Bootstrap/JQuery](product-catalog/dotnet-jquery-bootstrap-app)
|
||||
|
||||
This project contains an example implementation of ASP.NET Core application that shows list of products and enables you to add, edit, or delete products. You can learn how to create web application on the existing database schema using new JSON functionalities that are available in SQL Server 2016 (or higher) and Azure SQL Database.
|
||||
This project contains an example implementation of ASP.NET Core application that shows list of products and enables you to add, edit, or delete products. You can learn how to create web application on the existing database schema using new JSON functionalities that are available in SQL Server 2016 (or higher) and Azure SQL Database.
|
||||
|
||||
[ReactJS Comments app - ASP.NET Core/Bootstrap/JQuery](comments/dotnet-react-jquery-app)
|
||||
|
||||
This project contains standard [ReactJS Comments tutorial app](https://github.com/reactjs/react-tutorial) with ASP.NET Core REST API. REST API is implemented using new JSON functionalities that are available in SQL Server 2016 (or higher) and Azure SQL Database.
|
|
@ -1,4 +1,7 @@
|
|||
use Clinic;
|
||||
go
|
||||
-- Create a non-sysadmin account for the application to use
|
||||
|
||||
CREATE LOGIN [ContosoClinicApplication] WITH PASSWORD = <enter a strong password here>
|
||||
CREATE USER [ContosoClinicApplication] FOR LOGIN [ContosoClinicApplication]
|
||||
EXEC sp_addrolemember N'db_datareader', N'ContosoClinicApplication'
|
||||
|
|
|
@ -28,7 +28,7 @@ To run this sample, you need the following prerequisites.
|
|||
**Software prerequisites:**
|
||||
|
||||
You can run the container with the following command.
|
||||
(Note the you'll need Windows Server Core TP5 v10.0.14300.1000.)
|
||||
(Note the you'll need Windows Server Core TP5 v10.0.14300.1030.)
|
||||
|
||||
````
|
||||
docker run -p 1433:1433 -v C:/temp/:C:/temp/ --env sa_password=<YOUR SA PASSWORD> --env attach_dbs="<DB-JSON-CONFIG>" microsoft/mssql-server-2014-express-windows
|
||||
|
|
Загрузка…
Ссылка в новой задаче