mirror of
https://github.com/Microsoft/sql-server-samples.git
synced 2025-12-08 14:58:54 +00:00
Merge remote-tracking branch 'refs/remotes/Microsoft/master'
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
|
||||
</startup>
|
||||
<connectionStrings>
|
||||
<add name="Db" connectionString="Server=tcp:YOUR_SERVER.database.windows.net,1433;Database=ConnectedCar;User ID=YOUR_USERNAME;Password=YOUR_PASSWORD;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;"/>
|
||||
</connectionStrings>
|
||||
<appSettings>
|
||||
<add key="insertSPName" value="InsertEvent"/> <!--Stored Procedure Name-->
|
||||
<add key="numberOfTasks" value="5"/> <!--Number of concurrent async tasks that the Data Generator will use-->
|
||||
<add key="numberOfCars" value="2500"/> <!--Number of unique cars-->
|
||||
<add key="batchSize" value="250"/> <!--Row Batch Size that every task produces-->
|
||||
<add key="commandDelay" value="10"/> <!--Delay between sql commands. You can set this to 0 for max high volume workload-->
|
||||
<add key="commandTimeout" value="600"/> <!--SQL Command Timeout-->
|
||||
<add key="enableShock" value="0"/> <!--Flag that turns on/off the data shock. This should be set to 0 for max high volume workload-->
|
||||
<add key="rpsFrequency" value="1000"/> <!--How frequently the Data Generator Rows Per Second(RPS) is polled-->
|
||||
<add key="logFileName" value="log.txt"/> <!--Log File Path-->
|
||||
|
||||
<!--random number generator settings-->
|
||||
<add key="HighSpeedProbabilityPower" value="0.5" />
|
||||
<add key="LowSpeedProbabilityPower" value="0.9" />
|
||||
<add key="HighOilProbabilityPower" value="0.3" />
|
||||
<add key="LowOilProbabilityPower" value="1.2" />
|
||||
<add key="HighTyrePressureProbabilityPower" value="0.5" />
|
||||
<add key="LowTyrePressureProbabilityPower" value="1.7" />
|
||||
<add key="HighOutsideTempProbabilityPower" value="0.3" />
|
||||
<add key="LowOutsideTempProbabilityPower" value="1.2" />
|
||||
<add key="HighEngineTempProbabilityPower" value="0.3" />
|
||||
<add key="LowEngineTempProbabilityPower" value="1.2" />
|
||||
</appSettings>
|
||||
</configuration>
|
||||
@@ -0,0 +1,21 @@
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace DataGenerator
|
||||
{
|
||||
internal struct CancellableTask
|
||||
{
|
||||
public CancellableTask(int id, Task task, CancellationTokenSource cancellationTokenSource)
|
||||
{
|
||||
this.Id = id;
|
||||
this.Task = task;
|
||||
this.CancellationTokenSource = cancellationTokenSource;
|
||||
}
|
||||
|
||||
public int Id { get; }
|
||||
|
||||
public Task Task { get; }
|
||||
|
||||
public CancellationTokenSource CancellationTokenSource { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{D871B062-06A7-49E3-8BCD-8465B772FC52}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>DataGenerator</RootNamespace>
|
||||
<AssemblyName>DataGenerator</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.configuration" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="CancellableTask.cs" />
|
||||
<Compile Include="SqlDataGeneratorException.cs" />
|
||||
<Compile Include="SqlDataGenerator.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
@@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("DataGenerator")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("DataGenerator")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2016")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("d871b062-06a7-49e3-8bcd-8465b772fc52")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
@@ -0,0 +1,457 @@
|
||||
//----------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
|
||||
// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
|
||||
// OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//----------------------------------------------------------------------------------
|
||||
// The example companies, organizations, products, domain names,
|
||||
// e-mail addresses, logos, people, places, and events depicted
|
||||
// herein are fictitious. No association with any real company,
|
||||
// organization, product, domain name, email address, logo, person,
|
||||
// places, or events is intended or should be inferred.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Data.SqlClient;
|
||||
using System.Data.Sql;
|
||||
using System.Data;
|
||||
using System.Diagnostics;
|
||||
using System.Collections.Concurrent;
|
||||
using Microsoft.SqlServer.Server;
|
||||
using System.Configuration;
|
||||
|
||||
|
||||
namespace DataGenerator
|
||||
{
|
||||
/// <summary>SqlDataGenerator is a class used for creating SQL Server sample data by using multiple Asychronous Tasks.</summary>
|
||||
public class SqlDataGenerator
|
||||
{
|
||||
private string[] postalCodes = {"98001","98002","98003","98004","98005","98006","98007","98008","98009","98010","98011","98012","98013","98014","98015","98019","98020","98021","98022","98023",
|
||||
"98024","98025","98026","98027","98028","98029","98030","98031","98032","98033","98034","98035","98036","98037","98038","98039","98040","98041","98042","98043",
|
||||
"98050","98051","98052","98053","98054","98055","98056","98057","98058","98059","98061","98062","98063","98064","98065","98068","98070","98071","98072","98073",
|
||||
"98074","98075","98077","98082","98083","98087","98089","98092","98093","98101","98102","98103","98104","98105","98106","98107","98108","98109","98110","98111"};
|
||||
|
||||
private Action<int, Exception> onException;
|
||||
private ConcurrentDictionary<int, CancellableTask> tasks;
|
||||
|
||||
private string sqlConnectionString;
|
||||
private string sqlInsertEventSPName;
|
||||
private int sqlCommandTimeout;
|
||||
private int batchSize;
|
||||
private int initialNumberOfTasks;
|
||||
private int numberOfCarsPerTask;
|
||||
private int numberOfBatchesPerTask;
|
||||
private int delay;
|
||||
private int numberOfCars;
|
||||
private Random random;
|
||||
|
||||
private Stopwatch timer;
|
||||
private int numberOfRowsInserted = 0;
|
||||
|
||||
protected ThreadLocal<Random> randomValue;
|
||||
private bool running = false;
|
||||
|
||||
/// <summary>Wait Time in milliseconds between executing SqlCommands.</summary>
|
||||
/// <returns>Integer</returns>
|
||||
public int Delay
|
||||
{
|
||||
get { return delay; }
|
||||
set
|
||||
{
|
||||
Validate(this.batchSize, this.initialNumberOfTasks, value, this.numberOfCars);
|
||||
delay = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>The row count of the sample data batch that every task generates.</summary>
|
||||
/// <returns>Integer</returns>
|
||||
public int BatchSize
|
||||
{
|
||||
get { return batchSize; }
|
||||
set
|
||||
{
|
||||
Validate(value, this.initialNumberOfTasks, this.delay, this.numberOfCars);
|
||||
batchSize = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Rows (inserted or updated) per second.</summary>
|
||||
/// <returns>Double</returns>
|
||||
public double Rps => (double)this.numberOfRowsInserted / this.timer.Elapsed.TotalSeconds;
|
||||
|
||||
/// <summary>The number of current active tasks.</summary>
|
||||
/// <returns>Integer</returns>
|
||||
public int RunningTasks => this.tasks.Count();
|
||||
|
||||
/// <summary>Running Status</summary>
|
||||
/// <returns>Bool</returns>
|
||||
public bool IsRunning => this.running;
|
||||
|
||||
/// <summary>Creates a new instance of the SqlDataGenerator Class.</summary>
|
||||
/// <param name="sqlConnectionString">The sqlserver connectionString. Example: "Data Source=.;Initial Catalog=DbName;Integrated Security=True"</param>
|
||||
/// <param name="sqlInsertSPName">The Insert Event sqlserver stored procedure. Example: "InsertCarEvent". Note that the sql stored procedure needs to accept exactly two parameters: @Batch AS (Your User Defined Table Type) and @BatchSize INT</param>
|
||||
/// <param name="sqlCommandTimeout">The sqlserver command timeout. Example: 600</param>
|
||||
/// <param name="numberOfCars">The total number of Cars. Example: 1000</param>
|
||||
/// <param name="initialNumberOfTasks">The number of concurrent tasks. Example: 5. Note that every task 1.Creates and opens a new sql connection 2.Creates a batch of BatchSize sample data and 3.Executes the sql stored procedure passed in sqlStoredProcedureName endless times until stopped by the user.</param>
|
||||
/// <param name="delayInMilliseconds">Delay in Millisecods betweeen Sql Commands. Example. 100</param>
|
||||
/// <param name="batchSize">The row count of the batch size to be used by every task. Example: 200</param>
|
||||
/// <param name="batchDataTypes">The pipe seperated column types of the batch table. Example. identity:1:1|string|datetime|double|int|guid</param>
|
||||
/// <param name="onException">Exception call back method with TaskId(int) and exception(Exception). Example: ExceptionCallback</param>
|
||||
public SqlDataGenerator(
|
||||
string sqlConnectionString,
|
||||
string sqlInsertSPName,
|
||||
int sqlCommandTimeout,
|
||||
int numberOfCars,
|
||||
int initialNumberOfTasks,
|
||||
int delayInMilliseconds,
|
||||
int batchSize,
|
||||
Action<int, Exception> onException)
|
||||
{
|
||||
|
||||
this.sqlConnectionString = sqlConnectionString;
|
||||
this.sqlInsertEventSPName = sqlInsertSPName;
|
||||
this.sqlCommandTimeout = sqlCommandTimeout;
|
||||
this.numberOfCars = numberOfCars;
|
||||
this.onException = onException;
|
||||
this.tasks = new ConcurrentDictionary<int, CancellableTask>();
|
||||
this.randomValue = new ThreadLocal<Random>(() => new Random(Guid.NewGuid().GetHashCode()));
|
||||
this.random = new Random();
|
||||
this.initialNumberOfTasks = initialNumberOfTasks;
|
||||
this.delay = delayInMilliseconds;
|
||||
this.batchSize = batchSize;
|
||||
|
||||
Validate(this.batchSize, this.initialNumberOfTasks, this.delay, this.numberOfCars);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>Creates and Starts all the tasks asynchronously. Note that every task 1.Creates and opens a new sql connection 2.Creates a batch of BatchSize sample data and 3.Executes the sql stored procedure passed in sqlStoredProcedureName endless times until stopped by the user.</summary>
|
||||
/// <returns>Task</returns>
|
||||
public async Task RunAsync()
|
||||
{
|
||||
if (this.running)
|
||||
{
|
||||
return;
|
||||
}
|
||||
timer = Stopwatch.StartNew();
|
||||
await this.RunAsync(this.initialNumberOfTasks);
|
||||
}
|
||||
|
||||
/// <summary>Stops all tasks asynchronously.</summary>
|
||||
/// <returns>Task</returns>
|
||||
public async Task StopAsync()
|
||||
{
|
||||
await this.StopAsync(this.RunningTasks);
|
||||
this.timer.Stop();
|
||||
this.numberOfRowsInserted = 0;
|
||||
}
|
||||
|
||||
/// <summary>Restarts the Rows/Second Counter. This is called internally every time the input is changed.</summary>
|
||||
/// <returns>void</returns>
|
||||
public void RpsReset()
|
||||
{
|
||||
if (running)
|
||||
{
|
||||
this.timer.Restart();
|
||||
this.numberOfRowsInserted = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Updates the number of tasks that the DataGenerator is using.</summary>
|
||||
/// <returns>Task</returns>
|
||||
/// <remarks></remarks>
|
||||
/// <param name="numberOfTasks">The number of Tasks to start/stop depending of the number of tasks currently running.</param>
|
||||
public async Task UpdateTasksAsync(int numberOfTasks)
|
||||
{
|
||||
int diff = numberOfTasks - this.RunningTasks;
|
||||
|
||||
if (!running || diff == 0)
|
||||
{
|
||||
this.initialNumberOfTasks = numberOfTasks;
|
||||
return;
|
||||
}
|
||||
|
||||
if (diff < 0)
|
||||
{
|
||||
await this.StopAsync(-diff);
|
||||
}
|
||||
else
|
||||
{
|
||||
await this.RunAsync(diff);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>InsertCarEventAsync(int taskId, CancellationToken token)</summary>
|
||||
/// <returns>Task</returns>
|
||||
/// <remarks>Every Task creates a new sql connection, creates a new sqlcommand, create a batch of random numbers, and executes indefinetely until stopped by the user.</remarks>
|
||||
/// <param name="taskId">The taskId</param>
|
||||
/// <param name="token">The task's CancellationToken</param>
|
||||
private async Task InsertCarEventAsync(int taskId, CancellationToken token)
|
||||
{
|
||||
int batchId = 0;
|
||||
int size = this.BatchSize;
|
||||
|
||||
using (SqlConnection connection = new SqlConnection(this.sqlConnectionString))
|
||||
{
|
||||
await connection.OpenAsync(token);
|
||||
|
||||
using (SqlCommand command = new SqlCommand())
|
||||
{
|
||||
command.Connection = connection;
|
||||
command.CommandType = CommandType.StoredProcedure;
|
||||
command.CommandTimeout = this.sqlCommandTimeout;
|
||||
command.CommandText = this.sqlInsertEventSPName;
|
||||
command.Parameters.Add("@Batch", SqlDbType.Structured);
|
||||
command.Parameters.Add("@BatchSize", SqlDbType.Int).Value = this.BatchSize;
|
||||
|
||||
while (!token.IsCancellationRequested)
|
||||
{
|
||||
DataTable dataTable = CreateBatch(taskId, batchId++);
|
||||
command.Parameters[0].Value = dataTable;
|
||||
|
||||
await command.ExecuteNonQueryAsync(token);
|
||||
Interlocked.Add(ref this.numberOfRowsInserted, size);
|
||||
await Task.Delay(this.Delay, token);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>CreateMeterMeasurementBatch(int taskId)</summary>
|
||||
/// <returns>DataTable</returns>
|
||||
/// <param name="taskId">Task Id</param>
|
||||
private DataTable CreateBatch(int taskId, int batchId)
|
||||
{
|
||||
DataTable table = new DataTable();
|
||||
table.Columns.Add("RowID", typeof(int));
|
||||
table.Columns.Add("EventID", typeof(Guid));
|
||||
table.Columns.Add("AutoID", typeof(int));
|
||||
table.Columns.Add("EventCategoryID", typeof(int));
|
||||
table.Columns.Add("EventMessage", typeof(string));
|
||||
table.Columns.Add("City", typeof(string));
|
||||
table.Columns.Add("OutsideTemperature", typeof(double));
|
||||
table.Columns.Add("EngineTemperature", typeof(double));
|
||||
table.Columns.Add("Speed", typeof(double));
|
||||
table.Columns.Add("Fuel", typeof(int));
|
||||
table.Columns.Add("EngineOil", typeof(double));
|
||||
table.Columns.Add("TirePressure", typeof(double));
|
||||
table.Columns.Add("Odometer", typeof(int));
|
||||
table.Columns.Add("AcceleratorPedalPosition", typeof(int));
|
||||
table.Columns.Add("ParkingBrakeStatus", typeof(bool));
|
||||
table.Columns.Add("HeadlampStatus", typeof(bool));
|
||||
table.Columns.Add("BrakePedalStatus", typeof(bool));
|
||||
table.Columns.Add("TransmissionGearPosition", typeof(int));
|
||||
table.Columns.Add("IgnitionStatus", typeof(bool));
|
||||
table.Columns.Add("WindshieldWiperStatus", typeof(bool));
|
||||
table.Columns.Add("Abs", typeof(bool));
|
||||
table.Columns.Add("PostalCode", typeof(string));
|
||||
table.Columns.Add("Timestamp", typeof(DateTime));
|
||||
|
||||
batchId = (batchId % this.numberOfBatchesPerTask);
|
||||
|
||||
for (int i = 1; i <= this.batchSize; i++)
|
||||
{
|
||||
int autoId = taskId * this.numberOfCarsPerTask + batchId * this.BatchSize + i;
|
||||
|
||||
Guid eventId = Guid.NewGuid();
|
||||
int eventCategoryId = 3; //Informational
|
||||
string eventMessage = "Informational";
|
||||
string city = GetCity();
|
||||
double outsideTemperature = GetOutsideTemp(city);
|
||||
double engineTemperature = GetEngineTemp(city);
|
||||
double speed = GetSpeed(city);
|
||||
int fuel = random.Next(0, 40);
|
||||
double engineOil = GetOil(city);
|
||||
double tirePressure = GetTirePressure(city);
|
||||
int odometer = random.Next(0, 200000);
|
||||
int acceleratorPedalPosition = random.Next(0, 100);
|
||||
bool parkingBrakeStatus = GetRandomBoolean();
|
||||
bool headlampStatus = GetRandomBoolean();
|
||||
bool brakePedalStatus = GetRandomBoolean();
|
||||
int transmissionGearPosition = GetGearPos();
|
||||
bool ignitionStatus = GetRandomBoolean();
|
||||
bool windshieldWiperStatus = GetRandomBoolean();
|
||||
bool abs = GetRandomBoolean();
|
||||
DateTime timestamp = DateTime.Now;
|
||||
int randomPostalCode = randomValue.Value.Next(0, this.postalCodes.Length);
|
||||
string postalCode = this.postalCodes[randomPostalCode].ToString();
|
||||
|
||||
table.Rows.Add(i, eventId, autoId, eventCategoryId, eventMessage, city, outsideTemperature,
|
||||
engineTemperature, speed, fuel, engineOil, tirePressure, odometer, acceleratorPedalPosition,
|
||||
parkingBrakeStatus, headlampStatus, brakePedalStatus, transmissionGearPosition, ignitionStatus, windshieldWiperStatus, abs, postalCode, timestamp);
|
||||
}
|
||||
return table;
|
||||
}
|
||||
|
||||
private static string GetCity()
|
||||
{
|
||||
List<string> list = new List<string>() { "Seattle", "Redmond", "Bellevue", "Sammamish", "Bellevue", "Bellevue", "Seattle", "Seattle", "Seattle", "Redmond", "Bellevue", "Redmond" };
|
||||
int l = list.Count;
|
||||
Random r = new Random();
|
||||
int num = r.Next(l);
|
||||
return list[num];
|
||||
}
|
||||
|
||||
private static int GetOutsideTemp(string city)
|
||||
{
|
||||
if (city.ToLower() == "seattle")
|
||||
{
|
||||
return GetRandomWeightedNumber(100, 0, Convert.ToDouble(ConfigurationManager.AppSettings["LowOutsideTempProbabilityPower"]));
|
||||
}
|
||||
return GetRandomWeightedNumber(100, 0, Convert.ToDouble(ConfigurationManager.AppSettings["HighOutsideTempProbabilityPower"]));
|
||||
}
|
||||
|
||||
private static int GetRandomWeightedNumber(int max, int min, double probabilityPower)
|
||||
{
|
||||
var randomizer = new Random();
|
||||
var randomDouble = randomizer.NextDouble();
|
||||
|
||||
var result = Math.Floor(min + (max + 1 - min) * (Math.Pow(randomDouble, probabilityPower)));
|
||||
return (int)result;
|
||||
}
|
||||
|
||||
static int GetEngineTemp(string city)
|
||||
{
|
||||
if (city.ToLower() == "seattle")
|
||||
{
|
||||
return GetRandomWeightedNumber(500, 0, Convert.ToDouble(ConfigurationManager.AppSettings["HighEngineTempProbabilityPower"]));
|
||||
}
|
||||
return GetRandomWeightedNumber(500, 0, Convert.ToDouble(ConfigurationManager.AppSettings["LowEngineTempProbabilityPower"]));
|
||||
}
|
||||
|
||||
static int GetSpeed(string city)
|
||||
{
|
||||
if (city.ToLower() == "bellevue")
|
||||
{
|
||||
return GetRandomWeightedNumber(100, 0, Convert.ToDouble(ConfigurationManager.AppSettings["HighSpeedProbabilityPower"]));
|
||||
}
|
||||
return GetRandomWeightedNumber(100, 0, Convert.ToDouble(ConfigurationManager.AppSettings["LowSpeedProbabilityPower"]));
|
||||
}
|
||||
|
||||
static int GetOil(string city)
|
||||
{
|
||||
if (city.ToLower() == "seattle")
|
||||
{
|
||||
return GetRandomWeightedNumber(50, 0, Convert.ToDouble(ConfigurationManager.AppSettings["LowOilProbabilityPower"]));
|
||||
}
|
||||
return GetRandomWeightedNumber(50, 0, Convert.ToDouble(ConfigurationManager.AppSettings["HighOilProbabilityPower"]));
|
||||
}
|
||||
|
||||
static bool GetRandomBoolean()
|
||||
{
|
||||
return new Random().Next(100) % 2 == 0;
|
||||
}
|
||||
|
||||
static int GetGearPos()
|
||||
{
|
||||
Random rnd = new Random();
|
||||
return rnd.Next(1, 8);
|
||||
}
|
||||
|
||||
/// <summary>StopAsync(int numberOfTasksToStop)</summary>
|
||||
/// <returns>Task</returns>
|
||||
/// <param name="numberOfTasksToStop">The number of Tasks to stop.</param>
|
||||
private async Task StopAsync(int numberOfTasksToStop)
|
||||
{
|
||||
// TODO: Lock
|
||||
if (numberOfTasksToStop >= this.RunningTasks) { this.running = false; }
|
||||
|
||||
numberOfTasksToStop = Math.Min(numberOfTasksToStop, this.RunningTasks);
|
||||
List<CancellableTask> cancellableTasksToKill = this.tasks.Take(numberOfTasksToStop).Select(kv => kv.Value).ToList();
|
||||
|
||||
foreach (CancellableTask cancellableTask in cancellableTasksToKill)
|
||||
{
|
||||
cancellableTask.CancellationTokenSource.Cancel();
|
||||
}
|
||||
|
||||
await Task.WhenAll(cancellableTasksToKill.Select(c => c.Task));
|
||||
}
|
||||
|
||||
static int GetTirePressure(string city)
|
||||
{
|
||||
if (city.ToLower() == "seattle")
|
||||
{
|
||||
return GetRandomWeightedNumber(50, 0, Convert.ToDouble(ConfigurationManager.AppSettings["LowTyrePressureProbabilityPower"]));
|
||||
}
|
||||
return GetRandomWeightedNumber(50, 0, Convert.ToDouble(ConfigurationManager.AppSettings["HighTyrePressureProbabilityPower"]));
|
||||
}
|
||||
|
||||
/// <summary>RunAsync(int numberOfTasks)</summary>
|
||||
/// <returns>Task</returns>
|
||||
/// <param name="numberOfTasks">The number of Tasks to start/stop depending of the number of tasks currently running.</param>
|
||||
private async Task RunAsync(int numberOfTasks)
|
||||
{
|
||||
for (int i = 0; i < numberOfTasks; i++)
|
||||
{
|
||||
CancellationTokenSource tokenSource = new CancellationTokenSource();
|
||||
int taskId = i;
|
||||
Task task = Task.Factory.StartNew(
|
||||
async () => await this.InsertCarEventAsync(taskId, tokenSource.Token).ContinueWith(t => CleanupTask(taskId, t)),
|
||||
tokenSource.Token,
|
||||
TaskCreationOptions.LongRunning,
|
||||
TaskScheduler.Default).Unwrap();
|
||||
|
||||
tasks.TryAdd(taskId, new CancellableTask(taskId, task, tokenSource));
|
||||
}
|
||||
|
||||
this.running = true;
|
||||
|
||||
await Task.WhenAll(this.tasks.Values.Select(t => t.Task));
|
||||
}
|
||||
|
||||
/// <summary>CleanupTask(int taskId, Task task)</summary>
|
||||
/// <returns>void</returns>
|
||||
/// <remarks></remarks>
|
||||
/// <param name="taskId">The taskId</param>
|
||||
/// <param name="task">The actual Task</param>
|
||||
private void CleanupTask(int taskId, Task task)
|
||||
{
|
||||
CancellableTask cancellableTask;
|
||||
bool succeeded = this.tasks.TryRemove(taskId, out cancellableTask);
|
||||
|
||||
if (task.IsFaulted && !cancellableTask.CancellationTokenSource.IsCancellationRequested)
|
||||
{
|
||||
this.onException(taskId, task.Exception?.InnerException);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Validate(int batchSize, int tasks, int delay)</summary>
|
||||
/// <param name="batchSize">The Batch Size</param>
|
||||
/// <param name="tasks">The number Of Tasks</param>
|
||||
/// <param name="delay">Teh Delay</param>
|
||||
private void Validate(int batchSize, int tasks, int delay, int numberOfCars)
|
||||
{
|
||||
// Validate
|
||||
if (batchSize <= 0)
|
||||
{
|
||||
throw new SqlDataGeneratorException("The Batch Size cannot be less or equal to zero.");
|
||||
}
|
||||
if (tasks <= 0)
|
||||
{
|
||||
throw new SqlDataGeneratorException("Number Of Tasks cannot be less or equal to zero.");
|
||||
}
|
||||
if (delay < 0)
|
||||
{
|
||||
throw new SqlDataGeneratorException("Delay cannot be less than zero");
|
||||
}
|
||||
if (numberOfCars <= 0)
|
||||
{
|
||||
throw new SqlDataGeneratorException("Number Of Meters cannot be less than zero");
|
||||
}
|
||||
if (numberOfCars < batchSize * tasks)
|
||||
{
|
||||
throw new SqlDataGeneratorException("Number Of Meters cannot be less than (Tasks * BatchSize).");
|
||||
}
|
||||
// Reset Rps
|
||||
RpsReset();
|
||||
|
||||
// Set Number Of Meters Per Tasks
|
||||
this.numberOfCarsPerTask = this.numberOfCars / this.initialNumberOfTasks;
|
||||
this.numberOfBatchesPerTask = this.numberOfCarsPerTask / this.BatchSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace DataGenerator
|
||||
{
|
||||
public class SqlDataGeneratorException : Exception
|
||||
{
|
||||
public SqlDataGeneratorException()
|
||||
:base()
|
||||
{
|
||||
}
|
||||
|
||||
public SqlDataGeneratorException(string message)
|
||||
:base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public SqlDataGeneratorException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
# IoT Connected Car
|
||||
This code sample demonstrates how a SQL Server 2016 (or higher) memory optimized database could be used to ingest a very high input data rate and ultimately help improve the performance of applications with this scenario. The code simulates an IoT Connected Car scenario where multiple cars are constantly sending telemetry data to an the Azure SQL database.
|
||||
|
||||
### 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
|
||||
|
||||
1. **Applies to:** SQL Server 2016 (or higher) Enterprise / Developer / Evaluation Edition, Azure SQL Database (Premium SKUs)
|
||||
2. **Key features:**
|
||||
- Memory Optimized Tables and Table valued Parameters (TVPs)
|
||||
- Natively Compiled Stored Procedures
|
||||
- System-Versioned Temporal Tables
|
||||
- Clustered Columnstore Index (CCI)
|
||||
- SQL Graph Extensions
|
||||
3. **Workload:** Data Ingestion for IoT
|
||||
4. **Programming Language:** .NET C#, T-SQL
|
||||
5. **Authors:** Perry Skountrianos [perrysk-msft]
|
||||
|
||||
<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 a Premium Azure SQL Database
|
||||
2. Visual Studio 2017 (or higher) with the latest SSDT installed
|
||||
|
||||
**Azure prerequisites:**
|
||||
|
||||
1. Permission to create an Azure SQL Database
|
||||
|
||||
<a name=run-this-sample></a>
|
||||
|
||||
## Run this sample
|
||||
1. Clone this repository using Git for Windows (http://www.git-scm.com/), or download the zip file.
|
||||
|
||||
2. From Visual Studio, open the **iot-connected-car.sln** file from the root directory.
|
||||
|
||||
3. Right click **WinFormsClient** and select "Set as StartUp Project" (if it is not already set).
|
||||
|
||||
4. In Visual Studio Build menu, select **Build Solution** (or Press F6).
|
||||
|
||||
5. Modify the **Db** connection string in **App.config Settings** (located in the **Solution Items** solution folder) to provide YOUR_SERVER, YOUR_USERNAME, and YOUR_PASSWORD
|
||||
|
||||
6. Create the Database and Sample reference data
|
||||
- Note: For publishing to Azure SQL you need to create a premium database before setting up the schema and sample data
|
||||
|
||||
7. Build the app and run it.
|
||||
|
||||
8. Press the **Setup/Reset DB** button to create the DB schema and sample reference data
|
||||
|
||||
9. Start the workload by pressing the **Start** button
|
||||
|
||||
<a name=sample-details></a>
|
||||
|
||||
## Sample details
|
||||
|
||||
**High Level Description**
|
||||
|
||||

|
||||
|
||||
**Visual Studio Solution Projects**
|
||||
|
||||
1. **Data Generator**: Data Generator client library. Uses multiple async tasks to produce a test data workload.
|
||||
2. **WinFormsClient**: Windows Forms Data Generator client.
|
||||
|
||||
<a name=disclaimers></a>
|
||||
|
||||
## Disclaimers
|
||||
The code included in this sample is not intended to be a set of best practices on how to build scalable enterprise grade applications. This is beyond the scope of this quick start sample.
|
||||
|
||||
<a name=related-links></a>
|
||||
|
||||
## Related Links
|
||||
|
||||
For more information, see these articles:
|
||||
- [In-Memory OLTP (In-Memory Optimization)] (https://msdn.microsoft.com/library/dn133186.aspx)
|
||||
- [OLTP and database management] (https://www.microsoft.com/server-cloud/solutions/oltp-database-management.aspx)
|
||||
- [SQL Server 2016 Temporal Tables] (https://msdn.microsoft.com/library/dn935015.aspx)
|
||||
- [In-Memory OLTP Common Design Pattern – High Data Input Rate/Shock Absorber] (https://blogs.technet.microsoft.com/dataplatforminsider/2013/09/19/in-memory-oltp-common-design-pattern-high-data-input-rateshock-absorber/)
|
||||
- [Power BI Download] (https://powerbi.microsoft.com/en-us/desktop/)
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
@@ -0,0 +1,288 @@
|
||||
namespace Client
|
||||
{
|
||||
partial class FrmMain
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.components = new System.ComponentModel.Container();
|
||||
System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea1 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
|
||||
System.Windows.Forms.DataVisualization.Charting.Legend legend1 = new System.Windows.Forms.DataVisualization.Charting.Legend();
|
||||
System.Windows.Forms.DataVisualization.Charting.Series series1 = new System.Windows.Forms.DataVisualization.Charting.Series();
|
||||
System.Windows.Forms.DataVisualization.Charting.DataPoint dataPoint1 = new System.Windows.Forms.DataVisualization.Charting.DataPoint(0D, 0D);
|
||||
this.bottomToolStrip = new System.Windows.Forms.ToolStrip();
|
||||
this.lblTasksTitle = new System.Windows.Forms.ToolStripLabel();
|
||||
this.lblTasksValue = new System.Windows.Forms.ToolStripLabel();
|
||||
this.tss_1 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.lblBatchSizeTitle = new System.Windows.Forms.ToolStripLabel();
|
||||
this.lblBatchSizeValue = new System.Windows.Forms.ToolStripLabel();
|
||||
this.tss_2 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.lblMetersTitle = new System.Windows.Forms.ToolStripLabel();
|
||||
this.lblMetersValue = new System.Windows.Forms.ToolStripLabel();
|
||||
this.Start = new System.Windows.Forms.Button();
|
||||
this.Stop = new System.Windows.Forms.Button();
|
||||
this.RpsChart = new System.Windows.Forms.DataVisualization.Charting.Chart();
|
||||
this.rpsTimer = new System.Windows.Forms.Timer(this.components);
|
||||
this.Reset = new System.Windows.Forms.Button();
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.lblRpsValue = new System.Windows.Forms.Label();
|
||||
this.bottomToolStrip.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.RpsChart)).BeginInit();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// bottomToolStrip
|
||||
//
|
||||
this.bottomToolStrip.BackColor = System.Drawing.Color.White;
|
||||
this.bottomToolStrip.Dock = System.Windows.Forms.DockStyle.Bottom;
|
||||
this.bottomToolStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.lblTasksTitle,
|
||||
this.lblTasksValue,
|
||||
this.tss_1,
|
||||
this.lblBatchSizeTitle,
|
||||
this.lblBatchSizeValue,
|
||||
this.tss_2,
|
||||
this.lblMetersTitle,
|
||||
this.lblMetersValue});
|
||||
this.bottomToolStrip.Location = new System.Drawing.Point(0, 535);
|
||||
this.bottomToolStrip.Name = "bottomToolStrip";
|
||||
this.bottomToolStrip.Size = new System.Drawing.Size(1209, 25);
|
||||
this.bottomToolStrip.TabIndex = 0;
|
||||
this.bottomToolStrip.Text = "toolStrip1";
|
||||
//
|
||||
// lblTasksTitle
|
||||
//
|
||||
this.lblTasksTitle.Font = new System.Drawing.Font("Segoe UI", 12F);
|
||||
this.lblTasksTitle.ForeColor = System.Drawing.Color.DimGray;
|
||||
this.lblTasksTitle.Name = "lblTasksTitle";
|
||||
this.lblTasksTitle.Size = new System.Drawing.Size(49, 22);
|
||||
this.lblTasksTitle.Text = "Tasks:";
|
||||
//
|
||||
// lblTasksValue
|
||||
//
|
||||
this.lblTasksValue.Font = new System.Drawing.Font("Segoe UI", 12F);
|
||||
this.lblTasksValue.Name = "lblTasksValue";
|
||||
this.lblTasksValue.Size = new System.Drawing.Size(19, 22);
|
||||
this.lblTasksValue.Text = "0";
|
||||
//
|
||||
// tss_1
|
||||
//
|
||||
this.tss_1.Name = "tss_1";
|
||||
this.tss_1.Size = new System.Drawing.Size(6, 25);
|
||||
//
|
||||
// lblBatchSizeTitle
|
||||
//
|
||||
this.lblBatchSizeTitle.Font = new System.Drawing.Font("Segoe UI", 12F);
|
||||
this.lblBatchSizeTitle.ForeColor = System.Drawing.Color.DimGray;
|
||||
this.lblBatchSizeTitle.Name = "lblBatchSizeTitle";
|
||||
this.lblBatchSizeTitle.Size = new System.Drawing.Size(83, 22);
|
||||
this.lblBatchSizeTitle.Text = "Batch Size:";
|
||||
//
|
||||
// lblBatchSizeValue
|
||||
//
|
||||
this.lblBatchSizeValue.Font = new System.Drawing.Font("Segoe UI", 12F);
|
||||
this.lblBatchSizeValue.Name = "lblBatchSizeValue";
|
||||
this.lblBatchSizeValue.Size = new System.Drawing.Size(19, 22);
|
||||
this.lblBatchSizeValue.Text = "0";
|
||||
//
|
||||
// tss_2
|
||||
//
|
||||
this.tss_2.Name = "tss_2";
|
||||
this.tss_2.Size = new System.Drawing.Size(6, 25);
|
||||
//
|
||||
// lblMetersTitle
|
||||
//
|
||||
this.lblMetersTitle.Font = new System.Drawing.Font("Segoe UI", 12F);
|
||||
this.lblMetersTitle.ForeColor = System.Drawing.Color.DimGray;
|
||||
this.lblMetersTitle.Name = "lblMetersTitle";
|
||||
this.lblMetersTitle.Size = new System.Drawing.Size(122, 22);
|
||||
this.lblMetersTitle.Text = "Connected Cars:";
|
||||
//
|
||||
// lblMetersValue
|
||||
//
|
||||
this.lblMetersValue.Font = new System.Drawing.Font("Segoe UI", 12F);
|
||||
this.lblMetersValue.Name = "lblMetersValue";
|
||||
this.lblMetersValue.Size = new System.Drawing.Size(19, 22);
|
||||
this.lblMetersValue.Text = "0";
|
||||
//
|
||||
// Start
|
||||
//
|
||||
this.Start.FlatAppearance.BorderColor = System.Drawing.Color.Silver;
|
||||
this.Start.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
||||
this.Start.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.Start.Location = new System.Drawing.Point(956, 498);
|
||||
this.Start.Name = "Start";
|
||||
this.Start.Size = new System.Drawing.Size(112, 50);
|
||||
this.Start.TabIndex = 2;
|
||||
this.Start.Text = "Start";
|
||||
this.Start.UseVisualStyleBackColor = true;
|
||||
this.Start.Click += new System.EventHandler(this.Start_Click);
|
||||
//
|
||||
// Stop
|
||||
//
|
||||
this.Stop.Enabled = false;
|
||||
this.Stop.FlatAppearance.BorderColor = System.Drawing.Color.Silver;
|
||||
this.Stop.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
||||
this.Stop.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.Stop.Location = new System.Drawing.Point(1074, 498);
|
||||
this.Stop.Name = "Stop";
|
||||
this.Stop.Size = new System.Drawing.Size(111, 50);
|
||||
this.Stop.TabIndex = 3;
|
||||
this.Stop.Text = "Stop";
|
||||
this.Stop.UseVisualStyleBackColor = true;
|
||||
this.Stop.Click += new System.EventHandler(this.Stop_Click);
|
||||
//
|
||||
// RpsChart
|
||||
//
|
||||
this.RpsChart.BackColor = System.Drawing.Color.Transparent;
|
||||
this.RpsChart.BorderlineColor = System.Drawing.Color.Black;
|
||||
chartArea1.AxisX.IntervalType = System.Windows.Forms.DataVisualization.Charting.DateTimeIntervalType.Seconds;
|
||||
chartArea1.AxisX.LabelAutoFitMaxFontSize = 8;
|
||||
chartArea1.AxisX.LineColor = System.Drawing.Color.DimGray;
|
||||
chartArea1.AxisX.MajorGrid.Enabled = false;
|
||||
chartArea1.AxisX.MajorGrid.Interval = 0D;
|
||||
chartArea1.AxisX.MajorGrid.IntervalOffset = 0D;
|
||||
chartArea1.AxisX.MajorGrid.IntervalType = System.Windows.Forms.DataVisualization.Charting.DateTimeIntervalType.Auto;
|
||||
chartArea1.AxisX.MajorTickMark.Enabled = false;
|
||||
chartArea1.AxisX.Maximum = 100D;
|
||||
chartArea1.AxisX.Minimum = 0D;
|
||||
chartArea1.AxisX.Title = "Seconds";
|
||||
chartArea1.AxisX.TitleFont = new System.Drawing.Font("Tahoma", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
chartArea1.AxisY.LabelAutoFitMaxFontSize = 8;
|
||||
chartArea1.AxisY.LineColor = System.Drawing.Color.DimGray;
|
||||
chartArea1.AxisY.MajorGrid.Enabled = false;
|
||||
chartArea1.AxisY.Minimum = 0D;
|
||||
chartArea1.AxisY.Title = "Number Of Events";
|
||||
chartArea1.AxisY.TitleFont = new System.Drawing.Font("Tahoma", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
chartArea1.BackColor = System.Drawing.Color.Transparent;
|
||||
chartArea1.Name = "Chart";
|
||||
this.RpsChart.ChartAreas.Add(chartArea1);
|
||||
legend1.BackColor = System.Drawing.Color.Transparent;
|
||||
legend1.Enabled = false;
|
||||
legend1.ForeColor = System.Drawing.Color.Maroon;
|
||||
legend1.Name = "Legend1";
|
||||
this.RpsChart.Legends.Add(legend1);
|
||||
this.RpsChart.Location = new System.Drawing.Point(0, 53);
|
||||
this.RpsChart.Name = "RpsChart";
|
||||
this.RpsChart.Palette = System.Windows.Forms.DataVisualization.Charting.ChartColorPalette.None;
|
||||
series1.ChartArea = "Chart";
|
||||
series1.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Area;
|
||||
series1.Color = System.Drawing.Color.Gray;
|
||||
series1.Font = new System.Drawing.Font("Microsoft Sans Serif", 6F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
series1.Legend = "Legend1";
|
||||
series1.LegendText = "sadsaDS";
|
||||
series1.MarkerBorderWidth = 3;
|
||||
series1.Name = "RPS";
|
||||
series1.Points.Add(dataPoint1);
|
||||
this.RpsChart.Series.Add(series1);
|
||||
this.RpsChart.Size = new System.Drawing.Size(1209, 419);
|
||||
this.RpsChart.TabIndex = 102;
|
||||
this.RpsChart.Text = "Rows / Sec";
|
||||
//
|
||||
// rpsTimer
|
||||
//
|
||||
this.rpsTimer.Interval = 300;
|
||||
this.rpsTimer.Tick += new System.EventHandler(this.rpsTimer_Tick);
|
||||
//
|
||||
// Reset
|
||||
//
|
||||
this.Reset.BackColor = System.Drawing.Color.White;
|
||||
this.Reset.FlatAppearance.BorderColor = System.Drawing.Color.Silver;
|
||||
this.Reset.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
||||
this.Reset.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.Reset.Location = new System.Drawing.Point(764, 498);
|
||||
this.Reset.Name = "Reset";
|
||||
this.Reset.Size = new System.Drawing.Size(160, 50);
|
||||
this.Reset.TabIndex = 103;
|
||||
this.Reset.Text = "Setup/Reset DB";
|
||||
this.Reset.UseVisualStyleBackColor = false;
|
||||
this.Reset.Click += new System.EventHandler(this.Reset_Click);
|
||||
//
|
||||
// label1
|
||||
//
|
||||
this.label1.AutoSize = true;
|
||||
this.label1.Font = new System.Drawing.Font("Microsoft Sans Serif", 22F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.label1.ForeColor = System.Drawing.Color.DimGray;
|
||||
this.label1.Location = new System.Drawing.Point(81, 14);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(168, 36);
|
||||
this.label1.TabIndex = 104;
|
||||
this.label1.Text = "Events/sec:";
|
||||
//
|
||||
// lblRpsValue
|
||||
//
|
||||
this.lblRpsValue.AutoSize = true;
|
||||
this.lblRpsValue.Font = new System.Drawing.Font("Microsoft Sans Serif", 21.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.lblRpsValue.ForeColor = System.Drawing.Color.Red;
|
||||
this.lblRpsValue.Location = new System.Drawing.Point(245, 17);
|
||||
this.lblRpsValue.Name = "lblRpsValue";
|
||||
this.lblRpsValue.Size = new System.Drawing.Size(31, 33);
|
||||
this.lblRpsValue.TabIndex = 105;
|
||||
this.lblRpsValue.Text = "0";
|
||||
//
|
||||
// FrmMain
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
|
||||
this.BackColor = System.Drawing.Color.White;
|
||||
this.ClientSize = new System.Drawing.Size(1209, 560);
|
||||
this.Controls.Add(this.lblRpsValue);
|
||||
this.Controls.Add(this.label1);
|
||||
this.Controls.Add(this.Reset);
|
||||
this.Controls.Add(this.RpsChart);
|
||||
this.Controls.Add(this.Stop);
|
||||
this.Controls.Add(this.Start);
|
||||
this.Controls.Add(this.bottomToolStrip);
|
||||
this.Name = "FrmMain";
|
||||
this.Text = "IoT Connected Car - Event Generator";
|
||||
this.bottomToolStrip.ResumeLayout(false);
|
||||
this.bottomToolStrip.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.RpsChart)).EndInit();
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.ToolStrip bottomToolStrip;
|
||||
private System.Windows.Forms.ToolStripLabel lblTasksTitle;
|
||||
private System.Windows.Forms.ToolStripLabel lblTasksValue;
|
||||
private System.Windows.Forms.ToolStripSeparator tss_1;
|
||||
private System.Windows.Forms.ToolStripLabel lblBatchSizeTitle;
|
||||
private System.Windows.Forms.ToolStripLabel lblBatchSizeValue;
|
||||
private System.Windows.Forms.ToolStripSeparator tss_2;
|
||||
private System.Windows.Forms.Button Start;
|
||||
private System.Windows.Forms.Button Stop;
|
||||
private System.Windows.Forms.DataVisualization.Charting.Chart RpsChart;
|
||||
private System.Windows.Forms.Timer rpsTimer;
|
||||
private System.Windows.Forms.ToolStripLabel lblMetersTitle;
|
||||
private System.Windows.Forms.ToolStripLabel lblMetersValue;
|
||||
private System.Windows.Forms.Button Reset;
|
||||
private System.Windows.Forms.Label label1;
|
||||
private System.Windows.Forms.Label lblRpsValue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,221 @@
|
||||
/*----------------------------------------------------------------------------------
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
|
||||
EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
----------------------------------------------------------------------------------
|
||||
The example companies, organizations, products, domain names,
|
||||
e-mail addresses, logos, people, places, and events depicted
|
||||
herein are fictitious. No association with any real company,
|
||||
organization, product, domain name, email address, logo, person,
|
||||
places, or events is intended or should be inferred.
|
||||
|
||||
*/
|
||||
|
||||
using DataGenerator;
|
||||
using System;
|
||||
using System.Configuration;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Windows.Forms;
|
||||
using System.Windows.Forms.DataVisualization.Charting;
|
||||
using System.Data;
|
||||
using System.Data.SqlClient;
|
||||
|
||||
/*----------------------------------------------------------------------------------
|
||||
High Level Scenario:
|
||||
This code sample demonstrates how a SQL Server 2016 (or higher) memory optimized database could be used to ingest a very high input data rate
|
||||
and ultimately help improve the performance of applications with this scenario. The code simulates an IoT Connected car scenario where multiple
|
||||
IoT telemetry data are constantly sending car events to the Azure SQL database.
|
||||
*/
|
||||
namespace Client
|
||||
{
|
||||
public partial class FrmMain : Form
|
||||
{
|
||||
private SqlDataGenerator dataGenerator;
|
||||
private string connection;
|
||||
private string spName;
|
||||
private string logFileName;
|
||||
private int tasks;
|
||||
private int cars;
|
||||
private int batchSize;
|
||||
private int delay;
|
||||
private int commandTimeout;
|
||||
private int rpsFrequency;
|
||||
private int rpsChartTime = 0;
|
||||
private int enableShock;
|
||||
|
||||
public FrmMain()
|
||||
{
|
||||
InitializeComponent();
|
||||
Init();
|
||||
|
||||
this.dataGenerator = new SqlDataGenerator(this.connection, this.spName, this.commandTimeout, this.cars, this.tasks, this.delay, this.batchSize, this.ExceptionCallback);
|
||||
}
|
||||
|
||||
private void ExceptionCallback(int taskId, Exception exception)
|
||||
{
|
||||
HandleException(exception, taskId);
|
||||
}
|
||||
|
||||
private void HandleException(Exception exception, int? taskId = null)
|
||||
{
|
||||
//string ex = taskId?.ToString() + " - " + exception.Message + (exception.InnerException != null ? "\n\nInner Exception\n" + exception.InnerException : "");
|
||||
|
||||
//MessageBox.Show(ex, "Invalid Input Parameter", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
|
||||
//using (StreamWriter w = File.AppendText(logFileName)) { w.WriteLine("\r\n{0}: {1}", DateTime.Now, ex); }
|
||||
}
|
||||
|
||||
private async void Start_Click(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.rpsTimer.Start();
|
||||
this.Stop.Enabled = true;
|
||||
this.Stop.Update();
|
||||
this.Start.Enabled = false;
|
||||
this.Start.Update();
|
||||
this.Reset.Enabled = false;
|
||||
this.Reset.Update();
|
||||
|
||||
await this.dataGenerator.RunAsync();
|
||||
}
|
||||
catch (Exception exception) { HandleException(exception); }
|
||||
}
|
||||
|
||||
private async void Stop_Click(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.UpdateChart(-1);
|
||||
this.rpsTimer.Stop();
|
||||
this.lblRpsValue.Text = "0";
|
||||
this.lblTasksValue.Text = "0";
|
||||
this.Stop.Enabled = false;
|
||||
this.Stop.Update();
|
||||
this.Start.Enabled = true;
|
||||
this.Start.Update();
|
||||
this.Reset.Enabled = true;
|
||||
this.Reset.Update();
|
||||
|
||||
await this.dataGenerator.StopAsync();
|
||||
this.dataGenerator.RpsReset();
|
||||
}
|
||||
catch (Exception exception) { HandleException(exception); }
|
||||
}
|
||||
|
||||
private void UpdateChart(double rps)
|
||||
{
|
||||
if (rps >= 0)
|
||||
{
|
||||
rpsChartTime++;
|
||||
|
||||
if (rpsChartTime > this.RpsChart.ChartAreas[0].AxisX.Maximum)
|
||||
{
|
||||
this.RpsChart.ChartAreas[0].AxisX.Maximum += 100;
|
||||
}
|
||||
this.RpsChart.Series[0].Points.Add(new DataPoint(rpsChartTime, rps));
|
||||
}
|
||||
else
|
||||
{
|
||||
this.RpsChart.Series[0].Points.Clear();
|
||||
rpsChartTime = 0;
|
||||
}
|
||||
this.RpsChart.Update();
|
||||
}
|
||||
|
||||
private void Init()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Read Config Settings
|
||||
this.connection = ConfigurationManager.ConnectionStrings["Db"].ConnectionString;
|
||||
this.spName = ConfigurationManager.AppSettings["insertSPName"];
|
||||
this.logFileName = ConfigurationManager.AppSettings["logFileName"];
|
||||
this.tasks = int.Parse(ConfigurationManager.AppSettings["numberOfTasks"]);
|
||||
this.cars = int.Parse(ConfigurationManager.AppSettings["numberOfCars"]);
|
||||
this.batchSize = int.Parse(ConfigurationManager.AppSettings["batchSize"]);
|
||||
this.delay = int.Parse(ConfigurationManager.AppSettings["commandDelay"]);
|
||||
this.commandTimeout = int.Parse(ConfigurationManager.AppSettings["commandTimeout"]);
|
||||
this.enableShock = int.Parse(ConfigurationManager.AppSettings["enableShock"]);
|
||||
|
||||
this.rpsFrequency = int.Parse(ConfigurationManager.AppSettings["rpsFrequency"]);
|
||||
|
||||
// Initialize Timers
|
||||
this.rpsTimer.Interval = this.rpsFrequency;
|
||||
|
||||
// Initialize Labels
|
||||
this.lblTasksValue.Text = string.Format("{0:#,#}", this.tasks).ToString();
|
||||
this.lblBatchSizeValue.Text = string.Format("{0:#,#}", this.batchSize).ToString();
|
||||
this.lblMetersValue.Text = string.Format("{0:#,#}", this.cars).ToString();
|
||||
|
||||
if (batchSize <= 0) throw new SqlDataGeneratorException("The Batch Size cannot be less or equal to zero.");
|
||||
|
||||
if (tasks <= 0) throw new SqlDataGeneratorException("Number Of Tasks cannot be less or equal to zero.");
|
||||
|
||||
if (delay < 0) throw new SqlDataGeneratorException("Delay cannot be less than zero");
|
||||
|
||||
if (cars <= 0) throw new SqlDataGeneratorException("Number Of Meters cannot be less than zero");
|
||||
|
||||
if (cars < batchSize * tasks) throw new SqlDataGeneratorException("Number Of Meters cannot be less than (Tasks * BatchSize).");
|
||||
}
|
||||
catch (Exception exception) { HandleException(exception); }
|
||||
}
|
||||
|
||||
private void rpsTimer_Tick(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.lblTasksValue.Text = this.dataGenerator.RunningTasks.ToString();
|
||||
|
||||
double rps = this.dataGenerator.Rps;
|
||||
if (dataGenerator.IsRunning)
|
||||
{
|
||||
if (this.dataGenerator.RunningTasks == 0) return;
|
||||
|
||||
if (rps > 0)
|
||||
{
|
||||
this.lblRpsValue.Text = string.Format("{0:#,#}", rps).ToString();
|
||||
UpdateChart(rps);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception exception) { HandleException(exception); }
|
||||
}
|
||||
|
||||
private void Reset_Click(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.Reset.Text = "Executing...";
|
||||
this.Reset.Update();
|
||||
|
||||
string script = File.ReadAllText(@"setup_reset.sql");
|
||||
|
||||
using (SqlConnection connection = new SqlConnection(this.connection))
|
||||
{
|
||||
connection.Open();
|
||||
|
||||
using (SqlCommand command = new SqlCommand())
|
||||
{
|
||||
command.Connection = connection;
|
||||
command.CommandType = CommandType.Text;
|
||||
command.CommandTimeout = 1800;
|
||||
command.CommandText = script;
|
||||
command.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception exception) {HandleException(exception); }
|
||||
finally
|
||||
{
|
||||
this.Reset.Text = "Setup/Reset DB";
|
||||
this.Reset.Update();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<metadata name="bottomToolStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>17, 17</value>
|
||||
</metadata>
|
||||
<metadata name="rpsTimer.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>159, 17</value>
|
||||
</metadata>
|
||||
<metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>81</value>
|
||||
</metadata>
|
||||
</root>
|
||||
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Client
|
||||
{
|
||||
static class Program
|
||||
{
|
||||
/// <summary>
|
||||
/// The main entry point for the application.
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
static void Main()
|
||||
{
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
Application.Run(new FrmMain());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("Client")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Client")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2016")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("6c0e1820-a10b-47da-b806-939cbcd0dd39")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Client.Properties {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Client.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Client.Properties
|
||||
{
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
|
||||
{
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
|
||||
public static Settings Default
|
||||
{
|
||||
get
|
||||
{
|
||||
return defaultInstance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
|
||||
<Profiles>
|
||||
<Profile Name="(Default)" />
|
||||
</Profiles>
|
||||
<Settings />
|
||||
</SettingsFile>
|
||||
@@ -0,0 +1,108 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{6C0E1820-A10B-47DA-B806-939CBCD0DD39}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Client</RootNamespace>
|
||||
<AssemblyName>Client</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.configuration" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Windows.Forms.DataVisualization" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Deployment" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="FrmMain.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="FrmMain.Designer.cs">
|
||||
<DependentUpon>FrmMain.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<EmbeddedResource Include="FrmMain.resx">
|
||||
<DependentUpon>FrmMain.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
</Compile>
|
||||
<None Include="..\App.config">
|
||||
<Link>App.config</Link>
|
||||
</None>
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
<Compile Include="Properties\Settings.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\DataGenerator\DataGenerator.csproj">
|
||||
<Project>{d871b062-06a7-49e3-8bcd-8465b772fc52}</Project>
|
||||
<Name>DataGenerator</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="..\setup_reset.sql">
|
||||
<Link>setup_reset.sql</Link>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="sample-sql-queries.sql">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
@@ -0,0 +1,83 @@
|
||||
--====================================================================
|
||||
-- Step 1: Sample Analytical Queries - While the Data Ingestion is going on
|
||||
--====================================================================
|
||||
-- Query the In-Memory OLTP Table for all the latest Safety Telemetry Events
|
||||
SELECT EventID,
|
||||
EventMessage,
|
||||
City,
|
||||
OutsideTemperature,
|
||||
EngineTemperature,
|
||||
Speed,
|
||||
Fuel,
|
||||
EngineOil,
|
||||
TirePressure,
|
||||
Odometer,
|
||||
AcceleratorPedalPosition,
|
||||
ParkingBrakeStatus,
|
||||
HeadlampStatus,
|
||||
BrakePedalStatus,
|
||||
TransmissionGearPosition,
|
||||
IgnitionStatus,
|
||||
WindshieldWiperStatus,
|
||||
Abs
|
||||
FROM Events
|
||||
WHERE EventCategoryId = 2; -- Safety Event
|
||||
|
||||
-- Query the Temporal Disk based Table for ALL Telemetry data for a specific car
|
||||
SELECT *
|
||||
FROM EventsHistory
|
||||
WHERE AutoID = 50;
|
||||
|
||||
SELECT EventMessage,
|
||||
AVG(Speed) AS AvgSpeed,
|
||||
AVG(EngineTemperature) AS AvgEngineTemperature,
|
||||
AVG(EngineOil) AS AvgEngineOil,
|
||||
AVG(TirePressure) AS AvgTirePressure,
|
||||
MIN(TransmissionGearPosition) AS MinGearPosition,
|
||||
MAX(TransmissionGearPosition) AS MinGearPosition,
|
||||
AVG(TransmissionGearPosition) AS AvgGearPosition
|
||||
FROM EventsHistory
|
||||
WHERE AutoID = 50
|
||||
GROUP BY EventMessage;
|
||||
|
||||
--=====================================================
|
||||
-- Step 2: Sample SQL Graph Queries with Nodes and Edges
|
||||
--=====================================================
|
||||
|
||||
-- Rohan's Cars
|
||||
SELECT p.fullname, a1.AutoID, a1.OwnerID, a1.VIN, a1.Make, a1.Model, a1.Year, a1.DriveTrain, a1.EngineType, a1.ExteriorColor, a1.InteriorColor, a1.Transmission
|
||||
FROM Person p, owns_auto o1, Auto a1
|
||||
WHERE MATCH(a1<-(o1)-p)
|
||||
AND p.PersonID = 81
|
||||
|
||||
-- Find all Rohan's friends who drive the same car as Rohan
|
||||
SELECT f.fullname, a.AutoID, a.VIN, a.Make, a.Model, a.Year, a.DriveTrain, a.EngineType, a.ExteriorColor, a.InteriorColor, a.Transmission
|
||||
FROM Person p, owns_auto o1, auto a1, is_friend_of isf, Person f, owns_auto o, auto a
|
||||
WHERE MATCH(a1<-(o1)-p-(isf)->f-(o)->a)
|
||||
AND p.PersonID = 81
|
||||
AND a1.model = a.model
|
||||
AND a1.model = 'Convertible 2DR'
|
||||
|
||||
-- Get driving score for Rohan and his friends
|
||||
SELECT p.fullname, dr.Rank, dr.Rating, dr.overall_score, dr.Trend, dr.rank_change
|
||||
FROM Person p, has_score h, DriveScore dr
|
||||
WHERE MATCH(p-(h)->dr)
|
||||
AND p.PersonID = 81
|
||||
UNION
|
||||
SELECT f.fullname, ds.Rank, ds.Rating, ds.overall_score, ds.Trend, ds.rank_change
|
||||
FROM Person pp, is_friend_of isfof, Person f, has_score hs, DriveScore ds
|
||||
WHERE MATCH(pp-(isfof)->f-(hs)->ds)
|
||||
and pp.PersonID = 81
|
||||
|
||||
-- Compare Rohan's Driving Score with Shreya's Driving Score
|
||||
SELECT p.fullname, dr.Rank, dr.Rating, dr.overall_score, dr.Trend
|
||||
FROM Person p, has_score h, DriveScore dr
|
||||
WHERE MATCH(p-(h)->dr)
|
||||
AND p.PersonID = 81 -- Rohan
|
||||
UNION
|
||||
SELECT p.fullname, dr.Rank, dr.Rating, dr.overall_score, dr.Trend
|
||||
FROM Person p, has_score h, DriveScore dr
|
||||
WHERE MATCH(p-(h)->dr)
|
||||
AND p.PersonID = 85 -- Shreya
|
||||
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
--====================================================================
|
||||
-- Step 1: Sample Analytical Queries - While the Data Ingestion is going on
|
||||
--====================================================================
|
||||
-- Query the In-Memory OLTP Table for all the latest Safety Telemetry Events
|
||||
SELECT EventID,
|
||||
EventMessage,
|
||||
City,
|
||||
OutsideTemperature,
|
||||
EngineTemperature,
|
||||
Speed,
|
||||
Fuel,
|
||||
EngineOil,
|
||||
TirePressure,
|
||||
Odometer,
|
||||
AcceleratorPedalPosition,
|
||||
ParkingBrakeStatus,
|
||||
HeadlampStatus,
|
||||
BrakePedalStatus,
|
||||
TransmissionGearPosition,
|
||||
IgnitionStatus,
|
||||
WindshieldWiperStatus,
|
||||
Abs
|
||||
FROM Events
|
||||
WHERE EventCategoryId = 2; -- Safety Event
|
||||
|
||||
-- Query the Temporal Disk based Table for ALL Telemetry data for a specific car
|
||||
SELECT *
|
||||
FROM EventsHistory
|
||||
WHERE AutoID = 50;
|
||||
|
||||
SELECT EventMessage,
|
||||
AVG(Speed) AS AvgSpeed,
|
||||
AVG(EngineTemperature) AS AvgEngineTemperature,
|
||||
AVG(EngineOil) AS AvgEngineOil,
|
||||
AVG(TirePressure) AS AvgTirePressure,
|
||||
MIN(TransmissionGearPosition) AS MinGearPosition,
|
||||
MAX(TransmissionGearPosition) AS MinGearPosition,
|
||||
AVG(TransmissionGearPosition) AS AvgGearPosition
|
||||
FROM EventsHistory
|
||||
WHERE AutoID = 50
|
||||
GROUP BY EventMessage;
|
||||
|
||||
--=====================================================
|
||||
-- Step 2: Sample SQL Graph Queries with Nodes and Edges
|
||||
--=====================================================
|
||||
|
||||
-- Rohan's Cars
|
||||
SELECT p.fullname, a1.AutoID, a1.OwnerID, a1.VIN, a1.Make, a1.Model, a1.Year, a1.DriveTrain, a1.EngineType, a1.ExteriorColor, a1.InteriorColor, a1.Transmission
|
||||
FROM Person p, owns_auto o1, Auto a1
|
||||
WHERE MATCH(a1<-(o1)-p)
|
||||
AND p.PersonID = 81
|
||||
|
||||
-- Find all Rohan's friends who drive the same car as Rohan
|
||||
SELECT f.fullname, a.AutoID, a.VIN, a.Make, a.Model, a.Year, a.DriveTrain, a.EngineType, a.ExteriorColor, a.InteriorColor, a.Transmission
|
||||
FROM Person p, owns_auto o1, auto a1, is_friend_of isf, Person f, owns_auto o, auto a
|
||||
WHERE MATCH(a1<-(o1)-p-(isf)->f-(o)->a)
|
||||
AND p.PersonID = 81
|
||||
AND a1.model = a.model
|
||||
AND a1.model = 'Convertible 2DR'
|
||||
|
||||
-- Get driving score for Rohan and his friends
|
||||
SELECT p.fullname, dr.Rank, dr.Rating, dr.overall_score, dr.Trend, dr.rank_change
|
||||
FROM Person p, has_score h, DriveScore dr
|
||||
WHERE MATCH(p-(h)->dr)
|
||||
AND p.PersonID = 81
|
||||
UNION
|
||||
SELECT f.fullname, ds.Rank, ds.Rating, ds.overall_score, ds.Trend, ds.rank_change
|
||||
FROM Person pp, is_friend_of isfof, Person f, has_score hs, DriveScore ds
|
||||
WHERE MATCH(pp-(isfof)->f-(hs)->ds)
|
||||
and pp.PersonID = 81
|
||||
|
||||
-- Compare Rohan's Driving Score with Shreya's Driving Score
|
||||
SELECT p.fullname, dr.Rank, dr.Rating, dr.overall_score, dr.Trend
|
||||
FROM Person p, has_score h, DriveScore dr
|
||||
WHERE MATCH(p-(h)->dr)
|
||||
AND p.PersonID = 81 -- Rohan
|
||||
UNION
|
||||
SELECT p.fullname, dr.Rank, dr.Rating, dr.overall_score, dr.Trend
|
||||
FROM Person p, has_score h, DriveScore dr
|
||||
WHERE MATCH(p-(h)->dr)
|
||||
AND p.PersonID = 85 -- Shreya
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user