1 people like it.
Like the snippet!
One script to create MS-SQL-database and host OWIN Web-server with SignalR-clients
One script to create MS-SQL-database and host OWIN Web-server with SignalR-clients
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
198:
199:
200:
201:
202:
203:
204:
205:
206:
207:
208:
209:
210:
211:
212:
213:
214:
215:
216:
217:
218:
219:
220:
221:
222:
223:
224:
225:
226:
227:
228:
229:
230:
231:
232:
233:
234:
235:
236:
237:
238:
239:
240:
241:
242:
243:
244:
245:
246:
247:
248:
249:
250:
251:
252:
253:
254:
255:
256:
257:
258:
259:
260:
261:
262:
263:
264:
265:
266:
267:
268:
269:
270:
271:
272:
273:
274:
275:
276:
277:
278:
279:
280:
281:
282:
283:
284:
285:
286:
287:
288:
289:
290:
291:
292:
|
#if INTERACTIVE
open System
open System.IO
Console.WriteLine "Downloading components, etc. Will take a while."
// Run as admin, developer command prompt or F# Interactive. e.g. "fsi myfile.fsx"
[<Literal>]
let connectionString = "Data Source=localhost; Initial Catalog=myDatabase; Integrated Security=True;"
let serverDir = __SOURCE_DIRECTORY__ + @"/frontend"
// --- Package Restore ------------------------------------
Environment.CurrentDirectory <- __SOURCE_DIRECTORY__
if not <| File.Exists "paket.exe" then
let url = "https://github.com/fsprojects/Paket/releases/download/1.18.0/paket.exe"
use wc = new Net.WebClient ()
let tmp = Path.GetTempFileName ()
wc.DownloadFile (url, tmp);
File.Move (tmp,Path.GetFileName url)
#r "paket.exe"
Paket.Dependencies.Install """
source https://nuget.org/api/v2
nuget FAKE
nuget FSharp.Formatting
nuget FSharp.Data
nuget FSharp.Data.SqlClient
nuget Microsoft.AspNet.SignalR.Core
nuget Microsoft.AspNet.WebApi.OwinSelfHost
nuget Microsoft.Owin.Cors
nuget Microsoft.Owin.StaticFiles
nuget Rx-Main
nuget SQLProvider
nuget SourceLink.Fake
""";; // Rx-Main and SourceLink are for future use only...
// --- Drop and Create a Database ------------------------------------
#I @"./packages/FAKE/tools"
#r @"./packages/FAKE/tools/FakeLib.dll"
#r @"./packages/FAKE/tools/Fake.SQL.dll"
open Fake
open Fake.SQL
let SqlServerConnection = connectionString |> getServerInfo
SqlServerConnection |> SqlServer.DropDb |> ignore
SqlServerConnection |> SqlServer.CreateDb |> ignore
// Wouldn't need this if you have the DB already or install it from Fake scripts
// like this: SqlServer.runScript SqlServerConnection "createtables.sql"
#r @"./packages/FSharp.Data.SqlClient/lib/net40/FSharp.Data.SqlClient.dll"
open FSharp.Data
// Create Tables
[<Literal>]
let personTable="""
CREATE TABLE dbo.Person(
Id int NOT NULL IDENTITY (1, 1) PRIMARY KEY,
FirstName nvarchar(255) NOT NULL,
LastName nvarchar(255) NOT NULL
) ON [PRIMARY]
"""
[<Literal>]
let orderTable="""
CREATE TABLE dbo.[Order](
Id int NOT NULL IDENTITY (1, 1) PRIMARY KEY,
PersonId int NOT NULL,
Amount decimal(18, 0) NOT NULL,
OrderDate smalldatetime NOT NULL
) ON [PRIMARY]
"""
async {
use cmd1 = new SqlCommandProvider<personTable, connectionString>()
let! p = cmd1.AsyncExecute()
use cmd2 = new SqlCommandProvider<orderTable, connectionString>()
let! o = cmd2.AsyncExecute()
return p+o
} |> Async.RunSynchronously;;
// Insert Demo Data
[<Literal>]
let demoData="INSERT INTO [dbo].[Person] ([FirstName],[LastName]) VALUES (@firstName, @lastName)"
async {
use cmd3 = new SqlCommandProvider<demoData, connectionString>()
let! i1 = cmd3.AsyncExecute(firstName = "John", lastName = "Doe")
let! i2 = cmd3.AsyncExecute(firstName = "Tuomas", lastName = "Hietanen")
return i1+i2
} |> Async.RunSynchronously
// --- Create a HTML-Page ------------------------------------
// Could also load from separate files :-)
let page = """
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta charset="UTF-8" />
<title>My Site</title>
<!--script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-2.1.4.min.js"></script-->
<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-2.1.4.js"></script>
<!--script src="http://ajax.aspnetcdn.com/ajax/signalr/jquery.signalr-2.2.0.min.js"></script-->
<script src="http://ajax.aspnetcdn.com/ajax/signalr/jquery.signalr-2.2.0.js"></script>
<script type="text/javascript" src="/signalr/hubs"></script>
<script type="text/javascript">
var personList = {};
$(document).ready(function () {
//SignalR Hub:
var signalHub;
$.connection.hub.url = "/signalr";
signalHub = $.connection.SignalHub; //Hub class
if (!signalHub) console.log("hub not found");
signalHub.client.listPersons = function (data) {
data.forEach(function(itm) {
$('#peopleSelect')
.append($("<option></option>")
.attr("value",itm.Item1)
.text(itm.Item2));
personList[itm.Item1] = itm.Item2;
});
};
signalHub.client.acceptedOrder = function (data) {
alert(data);
};
signalHub.client.NotifyAll = function (id, myDay) {
alert("Hi all! New order for person " + personList[id] + " added to the system at " + myDay + ". ");
};
$.connection.hub.logging = true;
$.connection.hub.start().
done(function () {
$("#btn1").click(function () {
var person = $('#peopleSelect').val();
var ms = new Date();
signalHub.server.createOrder(person, ms);
return false;
});
});
});
</script>
<style>
.bgFrame {
background-color: #ffffff;
border: thin solid #000000;
padding: 30px;
margin: 30px;
width: 600px;
height: 200px;
vertical-align: middle;
text-align: center;
}
</style>
</head>
<body style="background-color: #cc99ff">
<div class="bgFrame">
<h2>Create orders for persons:</h2><br />
<form method="post" action="index.html">
<select id="peopleSelect"></select><br />
<input type="button" id="btn1" value="Place new order!" />
</form>
</div>
</body>
</html>
"""
if not <| Directory.Exists serverDir then
Directory.CreateDirectory serverDir |> ignore
let filename = serverDir + @"/index.html"
if File.Exists filename then
File.Delete filename
File.WriteAllText (filename, page)
// --- Load the References ------------------------------------
// Yes you can run this OWIN server also from Mono! Mono needs #I:s...
#r @"./packages/FSharp.Data/lib/net40/FSharp.Data.dll"
#r @"./packages/SQLProvider/lib/net40/FSharp.Data.SqlProvider.dll"
// OWIN and SignalR-packages:
#I @"./packages/Microsoft.AspNet.SignalR.Core/lib/net45"
#r @"./packages/Microsoft.AspNet.SignalR.Core/lib/net45/Microsoft.AspNet.SignalR.Core.dll"
#I @"./packages/Microsoft.Owin/lib/net45"
#r @"./packages/Microsoft.Owin/lib/net45/Microsoft.Owin.dll"
#I @"./packages/Microsoft.Owin.Security/lib/net45"
#r @"./packages/Microsoft.Owin.Security/lib/net45/Microsoft.Owin.Security.dll"
#I @"./packages/Microsoft.Owin.Hosting/lib/net45"
#r @"./packages/Microsoft.Owin.Hosting/lib/net45/Microsoft.Owin.Hosting.dll"
#I @"./packages/Microsoft.Owin.Host.HttpListener/lib/net45"
#r @"./packages/Microsoft.Owin.Host.HttpListener/lib/net45/Microsoft.Owin.Host.HttpListener.dll"
#I @"./packages/Microsoft.Owin.StaticFiles/lib/net45"
#r @"./packages/Microsoft.Owin.StaticFiles/lib/net45/Microsoft.Owin.StaticFiles.dll"
#I @"./packages/Microsoft.Owin.FileSystems/lib/net45"
#r @"./packages/Microsoft.Owin.FileSystems/lib/net45/Microsoft.Owin.FileSystems.dll"
#I @"./packages/Newtonsoft.Json/lib/net45"
#r @"./packages/Newtonsoft.Json/lib/net45/Newtonsoft.Json.dll"
#I @"./packages/Owin/lib/net40"
#r @"./packages/Owin/lib/net40/Owin.dll"
#else
// Use paket to manage project references.
module myServer
#endif
// --- SQL-Server Connection ------------------------------------
open FSharp.Data
open FSharp.Data.Sql
type SqlConnection =
SqlDataProvider< // Supports SQL-Server, Oracle, MySql, Odbc, etc.
ConnectionString = connectionString,
DatabaseVendor = Common.DatabaseProviderTypes.MSSQLSERVER,
IndividualsAmount = 1000,
UseOptionTypes = true>
// --- Communication to Clients ------------------------------------
open System
open System.Linq
open Microsoft.AspNet.SignalR
open Microsoft.AspNet.SignalR.Hubs
open System.Threading.Tasks
type MessageToClient = // Server can push data to single or all clients
abstract ListPersons : seq<int * string> -> Task
abstract AcceptedOrder : string -> Task
abstract NotifyAll : int * DateTime -> Task
[<HubName("SignalHub")>]
type SignalHub() as this =
inherit Hub<MessageToClient>()
override __.OnConnected() =
base.OnConnected() |> ignore
let context = SqlConnection.GetDataContext()
let items =
query {
for c in context.``[dbo].[Person]`` do
// where (c.Id < 100000)
select (c.Id, c.FirstName + " " + c.LastName)
} |> Seq.toArray
// printfn "Client connected: %s" this.Context.ConnectionId
this.Clients.Caller.ListPersons items
member __.CreateOrder (personId:int) (time:DateTime) =
let context = SqlConnection.GetDataContext()
let itm = context.``[dbo].[Order]``.Create(
1.0m,
PersonId = personId,
OrderDate = time
) // or could also use SqlCommandProvider...
context.SubmitUpdates()
this.Clients.Caller.AcceptedOrder "Thanks for the order!" |> ignore
this.Clients.All.NotifyAll (personId, time)
let hubConfig = HubConfiguration(EnableDetailedErrors = true, EnableJavaScriptProxies = true)
type MyWebStartup() =
member x.Configuration(ap:Owin.IAppBuilder) =
//OWIN Component registrations here...
//SignalR:
let app = Owin.OwinExtensions.MapSignalR(ap, hubConfig)
//Static files server (Note: default FileSystem is current directory!)
let fileServerOptions = Microsoft.Owin.StaticFiles.FileServerOptions()
fileServerOptions.DefaultFilesOptions.DefaultFileNames.Add "index.html"
fileServerOptions.FileSystem <- Microsoft.Owin.FileSystems.PhysicalFileSystem <| serverDir
Owin.FileServerExtensions.UseFileServer(app, fileServerOptions) |> ignore
()
[<assembly: Microsoft.Owin.OwinStartup(typeof<MyWebStartup>)>]
do()
let url = "http://localhost:7000"
let server = Microsoft.Owin.Hosting.WebApp.Start<MyWebStartup> url
Console.WriteLine ("Server started at: " + url)
Console.WriteLine "Press Enter to stop & quit."
Console.ReadLine()
server.Dispose()
|
Multiple items
union case CodeLanguage.FSharp: CodeLanguage
--------------------
namespace Microsoft.FSharp
namespace Microsoft.FSharp.Data
type SqlConnection = obj
Full name: Script.SqlConnection
val connectionString : string
Full name: Script.connectionString
Multiple items
union case ServiceInstallStart.System: ServiceInstallStart
--------------------
namespace System
namespace System.Linq
namespace Microsoft
namespace System.Threading
namespace System.Threading.Tasks
type MessageToClient =
interface
abstract member AcceptedOrder : string -> Task
abstract member ListPersons : seq<int * string> -> Task
abstract member NotifyAll : int * DateTime -> Task
end
Full name: Script.MessageToClient
abstract member MessageToClient.ListPersons : seq<int * string> -> Task
Full name: Script.MessageToClient.ListPersons
Multiple items
val seq : sequence:seq<'T> -> seq<'T>
Full name: Microsoft.FSharp.Core.Operators.seq
--------------------
type seq<'T> = Collections.Generic.IEnumerable<'T>
Full name: Microsoft.FSharp.Collections.seq<_>
Multiple items
val int : value:'T -> int (requires member op_Explicit)
Full name: Microsoft.FSharp.Core.Operators.int
--------------------
type int = int32
Full name: Microsoft.FSharp.Core.int
--------------------
type int<'Measure> = int
Full name: Microsoft.FSharp.Core.int<_>
Multiple items
val string : value:'T -> string
Full name: Microsoft.FSharp.Core.Operators.string
--------------------
type string = String
Full name: Microsoft.FSharp.Core.string
Multiple items
type Task =
new : action:Action -> Task + 7 overloads
member AsyncState : obj
member ContinueWith : continuationAction:Action<Task> -> Task + 9 overloads
member CreationOptions : TaskCreationOptions
member Dispose : unit -> unit
member Exception : AggregateException
member Id : int
member IsCanceled : bool
member IsCompleted : bool
member IsFaulted : bool
...
Full name: System.Threading.Tasks.Task
--------------------
type Task<'TResult> =
inherit Task
new : function:Func<'TResult> -> Task<'TResult> + 7 overloads
member ContinueWith : continuationAction:Action<Task<'TResult>> -> Task + 9 overloads
member Result : 'TResult with get, set
static member Factory : TaskFactory<'TResult>
Full name: System.Threading.Tasks.Task<_>
--------------------
Task(action: Action) : unit
Task(action: Action, cancellationToken: Threading.CancellationToken) : unit
Task(action: Action, creationOptions: TaskCreationOptions) : unit
Task(action: Action<obj>, state: obj) : unit
Task(action: Action, cancellationToken: Threading.CancellationToken, creationOptions: TaskCreationOptions) : unit
Task(action: Action<obj>, state: obj, cancellationToken: Threading.CancellationToken) : unit
Task(action: Action<obj>, state: obj, creationOptions: TaskCreationOptions) : unit
Task(action: Action<obj>, state: obj, cancellationToken: Threading.CancellationToken, creationOptions: TaskCreationOptions) : unit
--------------------
Task(function: Func<'TResult>) : unit
Task(function: Func<'TResult>, cancellationToken: Threading.CancellationToken) : unit
Task(function: Func<'TResult>, creationOptions: TaskCreationOptions) : unit
Task(function: Func<obj,'TResult>, state: obj) : unit
Task(function: Func<'TResult>, cancellationToken: Threading.CancellationToken, creationOptions: TaskCreationOptions) : unit
Task(function: Func<obj,'TResult>, state: obj, cancellationToken: Threading.CancellationToken) : unit
Task(function: Func<obj,'TResult>, state: obj, creationOptions: TaskCreationOptions) : unit
Task(function: Func<obj,'TResult>, state: obj, cancellationToken: Threading.CancellationToken, creationOptions: TaskCreationOptions) : unit
abstract member MessageToClient.AcceptedOrder : string -> Task
Full name: Script.MessageToClient.AcceptedOrder
abstract member MessageToClient.NotifyAll : int * DateTime -> Task
Full name: Script.MessageToClient.NotifyAll
Multiple items
type DateTime =
struct
new : ticks:int64 -> DateTime + 10 overloads
member Add : value:TimeSpan -> DateTime
member AddDays : value:float -> DateTime
member AddHours : value:float -> DateTime
member AddMilliseconds : value:float -> DateTime
member AddMinutes : value:float -> DateTime
member AddMonths : months:int -> DateTime
member AddSeconds : value:float -> DateTime
member AddTicks : value:int64 -> DateTime
member AddYears : value:int -> DateTime
...
end
Full name: System.DateTime
--------------------
DateTime()
(+0 other overloads)
DateTime(ticks: int64) : unit
(+0 other overloads)
DateTime(ticks: int64, kind: DateTimeKind) : unit
(+0 other overloads)
DateTime(year: int, month: int, day: int) : unit
(+0 other overloads)
DateTime(year: int, month: int, day: int, calendar: Globalization.Calendar) : unit
(+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int) : unit
(+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, kind: DateTimeKind) : unit
(+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, calendar: Globalization.Calendar) : unit
(+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, millisecond: int) : unit
(+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, millisecond: int, kind: DateTimeKind) : unit
(+0 other overloads)
Multiple items
type SignalHub =
inherit obj
new : unit -> SignalHub
member CreateOrder : personId:int -> time:DateTime -> 'a
override OnConnected : unit -> 'a
Full name: Script.SignalHub
--------------------
new : unit -> SignalHub
val this : SignalHub
override SignalHub.OnConnected : unit -> 'a
Full name: Script.SignalHub.OnConnected
val ignore : value:'T -> unit
Full name: Microsoft.FSharp.Core.Operators.ignore
val query : Linq.QueryBuilder
Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.query
module Seq
from Microsoft.FSharp.Collections
val toArray : source:seq<'T> -> 'T []
Full name: Microsoft.FSharp.Collections.Seq.toArray
member SignalHub.CreateOrder : personId:int -> time:DateTime -> 'a
Full name: Script.SignalHub.CreateOrder
val hubConfig : obj
Full name: Script.hubConfig
Multiple items
type MyWebStartup =
new : unit -> MyWebStartup
member Configuration : ap:'a -> unit
Full name: Script.MyWebStartup
--------------------
new : unit -> MyWebStartup
val x : MyWebStartup
Multiple items
member MyWebStartup.Configuration : ap:'a -> unit
Full name: Script.MyWebStartup.Configuration
--------------------
namespace System.Configuration
val ap : 'a
val app : obj
val fileServerOptions : obj
module FileSystem
from Fake
val serverDir : string
Full name: Script.serverDir
val typeof<'T> : Type
Full name: Microsoft.FSharp.Core.Operators.typeof
val url : string
Full name: Script.url
val server : obj
Full name: Script.server
type Console =
static member BackgroundColor : ConsoleColor with get, set
static member Beep : unit -> unit + 1 overload
static member BufferHeight : int with get, set
static member BufferWidth : int with get, set
static member CapsLock : bool
static member Clear : unit -> unit
static member CursorLeft : int with get, set
static member CursorSize : int with get, set
static member CursorTop : int with get, set
static member CursorVisible : bool with get, set
...
Full name: System.Console
Console.WriteLine() : unit
(+0 other overloads)
Console.WriteLine(value: string) : unit
(+0 other overloads)
Console.WriteLine(value: obj) : unit
(+0 other overloads)
Console.WriteLine(value: uint64) : unit
(+0 other overloads)
Console.WriteLine(value: int64) : unit
(+0 other overloads)
Console.WriteLine(value: uint32) : unit
(+0 other overloads)
Console.WriteLine(value: int) : unit
(+0 other overloads)
Console.WriteLine(value: float32) : unit
(+0 other overloads)
Console.WriteLine(value: float) : unit
(+0 other overloads)
Console.WriteLine(value: decimal) : unit
(+0 other overloads)
Console.ReadLine() : string
More information