Skip to content

Instantly share code, notes, and snippets.

@ImaginaryDevelopment
Last active December 21, 2015 21:44
Show Gist options
  • Save ImaginaryDevelopment/07f46bcf388fd8a75da7 to your computer and use it in GitHub Desktop.
Save ImaginaryDevelopment/07f46bcf388fd8a75da7 to your computer and use it in GitHub Desktop.
Templatus generate F# from sql table
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<!-- for build server primarily -->
<FSharpTargetsPath Condition="'$(FSharpTargetsPath)' == '' And Exists('C:\Program Files (x86)\Microsoft SDKs\F#\4.0\Framework\v4.0\Microsoft.FSharp.Targets')">C:\Program Files (x86)\Microsoft SDKs\F#\4.0\Framework\v4.0\Microsoft.FSharp.Targets</FSharpTargetsPath>
<FSharpTargetsPath Condition="'$(FSharpTargetsPath)' == '' And Exists('C:\Program Files (x86)\Microsoft SDKs\F#\3.1\Framework\v4.0')">C:\Program Files (x86)\Microsoft SDKs\F#\3.1\Framework\v4.0\Microsoft.FSharp.Targets</FSharpTargetsPath>
<FSharpTargetsPath Condition="'$(FSharpTargetsPath)' == '' ">..\3rdParty\Microsoft.FSharp.Targets</FSharpTargetsPath>
<!-- love these option settings, but not required -->
<WarningLevel>5</WarningLevel>
<OtherFlags>--warnon:1182 --warnaserror-:0052</OtherFlags>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
<Choose>
<When Condition="'$(VisualStudioVersion)' == '11.0'">
<PropertyGroup Condition="'$(FSharpTargetsPath)' == '' And Exists('$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets')">
<FSharpTargetsPath>$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets</FSharpTargetsPath>
</PropertyGroup>
</When>
<Otherwise>
<PropertyGroup Condition="'$(FSharpTargetsPath)' == '' And Exists('$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets')">
<FSharpTargetsPath>$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets</FSharpTargetsPath>
</PropertyGroup>
</Otherwise>
</Choose>
<Target Name="FDiagnostics" BeforeTargets="Build">
<Message Importance="high" Text="MSBuildExtensionsPath32:$(MSBuildExtensionsPath32)" />
<Message Importance="high" Text="FSharpTargetsPath:$(FSharpTargetsPath)" />
<Message Importance="high" Condition="Exists('$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets')" Text="FSharpTargetsPath:Exists" />
</Target>
<Import Project="$(FSharpTargetsPath)" />
</Project>
<!-- relevant changes to the fsproj here, not the entire fsproj file -->
<None Include="Template.ttus" />
<Content Include="template.txt" />
<!-- may not be relevant, but was helpful for build server -->
<Import Project="$(MSBuildProjectDirectory)\..\FTargets.proj" />
<!-- used if the templatus package starts working, otherwise not useful -->
<PropertyGroup>
<PackagesFolder>$([System.IO.Path]::GetFullPath('$(MSBuildProjectDirectory)\..\packages'))</PackagesFolder>
</PropertyGroup>
<!-- required for templatus, hard coded to point at my local build of templatus that seems to work locally in VS2015 SP1 -->
<!-- could stand to be updated to pull in all .ttus files in the project via msbuild item group -->
<Target Name="Templates" BeforeTargets="Compile;Build" Inputs="Template.ttus" Outputs="output.txt">
<Exec Command="C:\projects\Templatus\bin\Templatus.exe -t &quot;$(MSBuildProjectDirectory)\Template.ttus&quot; -p name=Timmy;age=3" Outputs="output.txt" />
<!-- <Exec Command="$(PackagesFolder)\Templatus.0.2.0\tools\Templatus.exe -t &quot;$(MSBuildProjectDirectory)\Template.ttus&quot; -p name=Timmy;age=3" Outputs="output.txt" /> -->
</Target>
<#@ assembly name="C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Data.Entity.Design.dll" #>
<#@ output filename="template.txt" #>
<#
// really only handles the sql, pluralizer, and creating a string builder with all the generated code content (doesn't break up into individual files, or check out automagically)
#>
Params: <#= sprintf "Name: %s, Age: %s" name age #>
Indented numbers:
<#
[1 .. 10]
|> Seq.iter (fun num -> pushIndent " "; tprintfn "%d" num)
[9 .. -1 .. 1]
|> Seq.iter (fun num -> popIndent (); sprintf "%d" num |> tprintn)
clearIndent ()
tprintn "----"
open System
open System.Collections.Generic
open System.Linq
type CultureInfo = System.Globalization.CultureInfo
type StringBuilder = System.Text.StringBuilder
type PluralizationService = System.Data.Entity.Design.PluralizationServices.PluralizationService
type ColumnDescription = {ColumnName:string; Type:string; Length:int; Nullable:bool; IsIdentity:bool}
let cString = "Data Source=<redacted>;Initial Catalog=ApplicationDatabase;App=Templatus;User Id=<redacted>;Password=<redacted>;"
let generateTypeComment columnCount = sprintf "/// %i properties" columnCount
let mapNullableType(targetType:string , nullable:bool, useOptions:bool ) = targetType + (if nullable then (if useOptions then " option" else " Nullable") else String.Empty)
let mapSqlType(type' : string, nullable:bool , useOptions:bool ) =
match type'.ToLower() with
|"char"
|"nchar"
|"nvarchar"
|"varchar" -> "string"
|"bit" -> mapNullableType("bool", nullable, useOptions)
|"date"
|"datetime"
|"smalldatetime" -> mapNullableType("DateTime", nullable, useOptions)
|"uniqueidentifier" -> mapNullableType("Guid",nullable, useOptions)
|"int" -> mapNullableType("int", nullable, useOptions)
|"decimal" -> mapNullableType("decimal", nullable, useOptions)
|"float" -> mapNullableType("float", nullable, useOptions)
|_ -> if isNull type' then String.Empty else type'
let generateColumnComment (cd:ColumnDescription) = sprintf "/// %s (%i) %s" (if isNull cd.Type then "null" else cd.Type) cd.Length (if cd.Nullable then "null" else "not null")
let generateInterface (typeName:string , columns:IEnumerable<ColumnDescription> , appendLine:int * string -> unit, writeable:bool , useOptions:bool ) =
appendLine(0, generateTypeComment (columns.Count()))
appendLine(0,"type I" + typeName + (if writeable then "RW" else String.Empty) + " =")
if writeable then
appendLine(1,"inherit I" + typeName)
for cd in columns do
appendLine(1, generateColumnComment cd)
appendLine(1, "abstract member " + cd.ColumnName + ":" + mapSqlType(cd.Type, cd.Nullable, useOptions) + " with get" + (if writeable then ",set" else String.Empty))
appendLine(0,String.Empty)
let getDefaultValue(mappedType:string ) =
if mappedType.EndsWith("Nullable") then
"Nullable()"
elif mappedType.EndsWith("option") then
"None"
else
match mappedType.ToLower() with
|"int" -> "0"
|"bool" -> "false"
|"decimal" -> "0m"
|"float" -> "0."
|"datetime" -> "System.DateTime.MinValue"
|"uniqueidentifier" -> "Guid.Empty"
|_ -> "null"
let generateRecord(typeName:string, columns: ColumnDescription seq, appendLine:int * string -> unit, useOptions:bool) =
appendLine(0, generateTypeComment (columns.Count()))
if not useOptions then
appendLine(0,"[<NoComparison>]")
appendLine(0, "type " + typeName + "Record =")
appendLine(1, "{")
for cd in columns do
appendLine(1, generateColumnComment(cd))
appendLine(1, cd.ColumnName + ":" + mapSqlType(cd.Type,cd.Nullable,useOptions))
appendLine(1,"}")
appendLine(1,"interface I" + typeName + " with")
for cd in columns do
appendLine(2, "member x." + cd.ColumnName + " with get () = x." + cd.ColumnName)
appendLine(1,"static member Zero () = ")
appendLine(2,"{")
for cd in columns do
let mapped = mapSqlType(cd.Type, cd.Nullable, useOptions)
appendLine(2, cd.ColumnName + " = " + getDefaultValue(mapped))
appendLine(2,"}")
appendLine(0,String.Empty)
let toCamel s = // https://github.com/ayoung/Newtonsoft.Json/blob/master/Newtonsoft.Json/Utilities/StringUtils.cs
if String.IsNullOrEmpty s then
s
elif not <| Char.IsUpper s.[0] then
s
else
let camelCase = Char.ToLower(s.[0], CultureInfo.InvariantCulture).ToString(CultureInfo.InvariantCulture)
if (s.Length > 1) then
camelCase + s.Substring(1)
else
camelCase
let generateModule(typeName:string, columns:IEnumerable<ColumnDescription>, schemaName:string , tableName:string , appendLine:int * string -> unit, useOptions:bool ) =
let camelType = toCamel typeName
appendLine(0, "module " + typeName + "Helpers =")
appendLine(1, "open Microsoft.FSharp.Core.Operators.Unchecked")
appendLine(1, String.Empty)
appendLine(1, "let tableName = \"" + typeName + "\"")
appendLine(1, "let ToRecord (i" + typeName + ":I" + typeName + ") =")
appendLine(2, "{")
for cd in columns do
let mapped = mapSqlType(cd.Type,cd.Nullable,useOptions)
appendLine(2, cd.ColumnName + " = i" + typeName + "." + cd.ColumnName)
appendLine(2, "}")
appendLine(0, String.Empty)
appendLine(1, "let toRecord (" + camelType + ":I"+ typeName + ") =")
appendLine(2, "{");
for cd in columns do
let mapped = mapSqlType(cd.Type,cd.Nullable,useOptions)
appendLine(2, cd.ColumnName + " = " + camelType + "." + cd.ColumnName)
appendLine(2, "}")
appendLine(0,String.Empty)
appendLine(1, "let FromF (camelTypeF:Func<string,obj option>) =")
appendLine(2, "{")
let mapConverter(type' : string , nullable: bool, useOptions:bool) =
match type'.ToLower() with
|"char"
|"nchar"
|"nvarchar"
|"varchar" -> "ToString"
|"bit" -> "ToBoolean"
|"date"
|"datetime"
|"smalldatetime" -> "ToDateTime"
|"uniqueidentifier" -> "ToGuid" // invalid
|"int" -> "ToInt32"
|"decimal" -> "ToDecimal"
|"float" -> "ToDouble"
|_ -> if isNull type' then String.Empty else type'
for cd in columns do
let mapped = mapSqlType(cd.Type,cd.Nullable,useOptions)
let converter = mapConverter(cd.Type,cd.Nullable,useOptions)
appendLine(2, cd.ColumnName + " = ")
appendLine(3, "match camelTypeF.Invoke \"" + cd.ColumnName + "\" with ")
if cd.Nullable && (mapped <> typeof<string>.Name) && (mapped <> "string") && mapped <> "String" then
appendLine(3, "|Some x -> Nullable (Convert." + converter + " x )")
else
appendLine(3, "|Some x -> Convert." + converter + " x ")
appendLine(3, "|None -> Unchecked.defaultof<_>")
appendLine(2, "}")
appendLine(0,String.Empty)
appendLine(1, "let inline toRecordStp (" + camelType + ": ^a) =")
appendLine(2, "{")
for cd in columns do
let mapped = mapSqlType(cd.Type,cd.Nullable,useOptions)
appendLine(2, cd.ColumnName + " = (^a: (member " + cd.ColumnName + ": _) " + camelType + ")")
appendLine(2, "}")
appendLine(0, String.Empty)
appendLine(1,"let createInsert (r:I" + typeName + ") =")
appendLine(2,"let quoted s = \"'\" + s + \"'\"")
let mapValue (cd:ColumnDescription, prefix:string) :string =
match cd.Type.ToLower() with
|"varchar" -> "if String.IsNullOrEmpty " + prefix + cd.ColumnName+ " then \"null\" else quoted " + prefix + cd.ColumnName
|"int" -> if cd.Nullable then "if isNull (box " + prefix + cd.ColumnName + ") then \"null\" else " + prefix + cd.ColumnName + " |> string" else prefix + cd.ColumnName + " |> string"
|_ -> if cd.Nullable then "if isNull (box " + prefix + cd.ColumnName + ") then \"null\" else " + prefix + cd.ColumnName + " |> string |> quoted" else prefix + cd.ColumnName + " |> string |> quoted"
appendLine(2,"[")
for cd in columns.Where(fun c -> not c.IsIdentity) do
let mapped = "\"" + cd.ColumnName + "\", " + mapValue(cd,"r.")
appendLine(3,mapped)
appendLine(2,"]")
appendLine(2,"|> fun pairs -> sprintf \"insert into " + schemaName + "." + tableName + "(%s) values (%s)\" (String.Join(\",\", pairs |> Seq.map fst )) (String.Join(\",\", pairs |> Seq.map snd))" )
appendLine(0,String.Empty)
let mapFieldNameFromType(columnName:string) =
match toCamel columnName with
| "type" -> "type'"
| camel -> camel
let generateClass(typeName:string, columns:IEnumerable<ColumnDescription> , appendLine:int * string -> unit, useOptions:bool ) =
appendLine(0, generateTypeComment (columns.Count()))
appendLine(0, "type "+ typeName + "N (model:" + typeName + "Record) = ")
appendLine(0, String.Empty)
appendLine(1, "let propertyChanged = new Event<_, _>()");
appendLine(0, String.Empty)
appendLine(0, String.Empty)
for cd in columns do // https://fadsworld.wordpress.com/2011/05/18/f-quotations-for-inotifypropertychanged/
let camel = mapFieldNameFromType(cd.ColumnName)
appendLine(1, "let mutable "+ camel + " = model." + cd.ColumnName)
appendLine(0, String.Empty)
appendLine(1, "interface I" + typeName + " with")
for cd in columns do
appendLine(2,generateColumnComment cd)
appendLine(2, "member x." + cd.ColumnName + " with get () = x." + cd.ColumnName)
appendLine(1, "interface I" + typeName + "RW with" )
for cd in columns do
appendLine(2,generateColumnComment cd)
appendLine(2, "member x." + cd.ColumnName + " with get () = x." + cd.ColumnName + " and set v = x." + cd.ColumnName + " <- v")
appendLine(0, String.Empty)
appendLine(1, "member x.MakeRecord () =")
appendLine(2, "{")
for cd in columns do
appendLine(2, cd.ColumnName + " = x." + cd.ColumnName)
appendLine(2, "}")
appendLine(0, String.Empty)
appendLine(1, "interface INotifyPropertyChanged with")
appendLine(2, "[<CLIEvent>]")
appendLine(2, "member x.PropertyChanged = propertyChanged.Publish")
appendLine(1, "abstract member RaisePropertyChanged : string -> unit")
appendLine(1, "default x.RaisePropertyChanged(propertyName : string) = propertyChanged.Trigger(x, PropertyChangedEventArgs(propertyName))")
appendLine(0, String.Empty)
appendLine(1, "abstract member SetAndNotify<'t> : string * 't byref * 't -> bool")
appendLine(1, "default x.SetAndNotify<'t> (propertyName, field: 't byref, value:'t) =")
appendLine(2, "if obj.ReferenceEquals(box field,box value) then false")
appendLine(2, "else")
appendLine(3, "field <- value")
appendLine(3, "x.RaisePropertyChanged(propertyNam)");
appendLine(3, "true")
appendLine(0, String.Empty)
appendLine(1, "abstract member SetAndNotify<'t,'b> : string * 'b * 't Action * 't -> bool")
appendLine(1, "default x.SetAndNotify<'t,'b> (propertyName, baseValue:'b, baseSetter: 't Action, value:'t) =")
appendLine(2, "if obj.ReferenceEquals(box baseValue,box value) then false")
appendLine(2, "else");
appendLine(3, "baseSetter.Invoke value")
appendLine(3, "x.RaisePropertyChanged(propertyName)")
appendLine(3, "true");
for cd in columns do
let camel = mapFieldNameFromType cd.ColumnName
appendLine(0, String.Empty)
appendLine(1, generateColumnComment cd)
appendLine(1, "member x." + cd.ColumnName)
appendLine(2, "with get() = " + camel)
appendLine(2, "and set v = ")
appendLine(3, camel + " <- v")
appendLine(3, "x.RaisePropertyChanged \"" + cd.ColumnName + "\"")
let generate (generationEnvironment:StringBuilder, targetProjectName:string, tables:string seq, cString:string) (pluralizer:string -> string) (singularizer:string -> string) useOptions =
let appendLine text = generationEnvironment.AppendLine(text) |> ignore
let appendLine' (indentLevels, text) = generationEnvironment.AppendLine(String.Join(String.Empty,Enumerable.Repeat(" ",indentLevels)) + text) |> ignore
use cn = new System.Data.SqlClient.SqlConnection(cString)
cn.Open()
for tableName in tables do
//manager.StartNewFile(Path.Combine(targetProjectFolder,tableName + ".generated.fs"),targetProject)
let typeName = singularizer tableName
let columns = List<ColumnDescription>()
let identities = List<string>()
use cmd = new System.Data.SqlClient.SqlCommand("sp_help " + tableName,cn)
use r = cmd.ExecuteReader()
r.NextResult() |> ignore // ignore the first table
while r.Read() do // column info
// columns and info
let columnName = r.["Column_name"].ToString()
let type' = r.["Type"].ToString()
// var computed = r["Computed"];
let length = Convert.ToInt32(r.["Length"])
// var prec = r["Prec"];
columns.Add {ColumnName=columnName; Type= type'; Length=length; Nullable = r.["Nullable"].ToString() ="yes"; IsIdentity = false}
r.NextResult() |> ignore
while r.Read() do // identities
if r.["Seed"] <> box System.DBNull.Value then // only valid identities (sql uses the identity column to say there are none defined instead of an empty set)
identities.Add(r.["Identity"].ToString())
let columns =
columns
|> Seq.map (fun c -> if identities.Contains(c.ColumnName) then {c with IsIdentity = true} else c)
|> fun s -> s.ToList()
let columns = columns.OrderBy(fun c -> c.ColumnName).ToList()
appendLine ("namespace Pm.Schema.DataModels." + (pluralizer typeName)) // + " // Generated by item in namespace " + manager.DefaultProjectNamespace )
appendLine String.Empty
appendLine "open System"
appendLine "open System.ComponentModel"
appendLine "open System.Linq.Expressions"
appendLine String.Empty
appendLine "open FSharp.NullHelpers"
generateInterface (typeName, columns, appendLine', false, useOptions)
generateInterface (typeName, columns, appendLine', true, useOptions)
generateRecord(typeName, columns, appendLine', useOptions)
generateModule(typeName, columns, "dbo", tableName, appendLine', useOptions)
generateClass(typeName, columns, appendLine', useOptions)
let sb = StringBuilder()
let pluralizer = PluralizationService.CreateService(CultureInfo "en") // https://msdn.microsoft.com/en-us/library/system.data.entity.design.pluralizationservices.pluralizationservice(v=vs.110).aspx
generate (sb, "Pm.Schema", ["Users"], cString) (pluralizer.Pluralize) (pluralizer.Singularize) false
tprint (sb.ToString())
#>
Params: Name: Timmy, Age: 3
Indented numbers:
1
2
3
4
5
6
7
8
9
10
9
8
7
6
5
4
3
2
1
----
namespace Pm.Schema.DataModels.Users
open System
open System.ComponentModel
open System.Linq.Expressions
open FSharp.NullHelpers
/// 13 properties
type IUser =
/// bit (1) not null
abstract member IsLockedOut:bool with get
/// int (4) not null
abstract member LoginAttempts:int with get
/// varchar (50) null
abstract member RcopiaID:string with get
/// bit (1) not null
abstract member ResetPassword:bool with get
/// int (4) not null
abstract member UserFacilityID:int with get
/// varchar (50) not null
abstract member UserFirstName:string with get
/// int (4) not null
abstract member UserID:int with get
/// varchar (50) not null
abstract member UserLastName:string with get
/// int (4) not null
abstract member UserLevel:int with get
/// varchar (1) null
abstract member UserMiddleInitial:string with get
/// varchar (50) null
abstract member UserName:string with get
/// varchar (50) not null
abstract member UserPassword:string with get
/// bit (1) not null
abstract member UserPreviouslyLoggedIn:bool with get
/// 13 properties
type IUserRW =
inherit IUser
/// bit (1) not null
abstract member IsLockedOut:bool with get,set
/// int (4) not null
abstract member LoginAttempts:int with get,set
/// varchar (50) null
abstract member RcopiaID:string with get,set
/// bit (1) not null
abstract member ResetPassword:bool with get,set
/// int (4) not null
abstract member UserFacilityID:int with get,set
/// varchar (50) not null
abstract member UserFirstName:string with get,set
/// int (4) not null
abstract member UserID:int with get,set
/// varchar (50) not null
abstract member UserLastName:string with get,set
/// int (4) not null
abstract member UserLevel:int with get,set
/// varchar (1) null
abstract member UserMiddleInitial:string with get,set
/// varchar (50) null
abstract member UserName:string with get,set
/// varchar (50) not null
abstract member UserPassword:string with get,set
/// bit (1) not null
abstract member UserPreviouslyLoggedIn:bool with get,set
/// 13 properties
[<NoComparison>]
type UserRecord =
{
/// bit (1) not null
IsLockedOut:bool
/// int (4) not null
LoginAttempts:int
/// varchar (50) null
RcopiaID:string
/// bit (1) not null
ResetPassword:bool
/// int (4) not null
UserFacilityID:int
/// varchar (50) not null
UserFirstName:string
/// int (4) not null
UserID:int
/// varchar (50) not null
UserLastName:string
/// int (4) not null
UserLevel:int
/// varchar (1) null
UserMiddleInitial:string
/// varchar (50) null
UserName:string
/// varchar (50) not null
UserPassword:string
/// bit (1) not null
UserPreviouslyLoggedIn:bool
}
interface IUser with
member x.IsLockedOut with get () = x.IsLockedOut
member x.LoginAttempts with get () = x.LoginAttempts
member x.RcopiaID with get () = x.RcopiaID
member x.ResetPassword with get () = x.ResetPassword
member x.UserFacilityID with get () = x.UserFacilityID
member x.UserFirstName with get () = x.UserFirstName
member x.UserID with get () = x.UserID
member x.UserLastName with get () = x.UserLastName
member x.UserLevel with get () = x.UserLevel
member x.UserMiddleInitial with get () = x.UserMiddleInitial
member x.UserName with get () = x.UserName
member x.UserPassword with get () = x.UserPassword
member x.UserPreviouslyLoggedIn with get () = x.UserPreviouslyLoggedIn
static member Zero () =
{
IsLockedOut = false
LoginAttempts = 0
RcopiaID = null
ResetPassword = false
UserFacilityID = 0
UserFirstName = null
UserID = 0
UserLastName = null
UserLevel = 0
UserMiddleInitial = null
UserName = null
UserPassword = null
UserPreviouslyLoggedIn = false
}
module UserHelpers =
open Microsoft.FSharp.Core.Operators.Unchecked
let tableName = "User"
let ToRecord (iUser:IUser) =
{
IsLockedOut = iUser.IsLockedOut
LoginAttempts = iUser.LoginAttempts
RcopiaID = iUser.RcopiaID
ResetPassword = iUser.ResetPassword
UserFacilityID = iUser.UserFacilityID
UserFirstName = iUser.UserFirstName
UserID = iUser.UserID
UserLastName = iUser.UserLastName
UserLevel = iUser.UserLevel
UserMiddleInitial = iUser.UserMiddleInitial
UserName = iUser.UserName
UserPassword = iUser.UserPassword
UserPreviouslyLoggedIn = iUser.UserPreviouslyLoggedIn
}
let toRecord (user:IUser) =
{
IsLockedOut = user.IsLockedOut
LoginAttempts = user.LoginAttempts
RcopiaID = user.RcopiaID
ResetPassword = user.ResetPassword
UserFacilityID = user.UserFacilityID
UserFirstName = user.UserFirstName
UserID = user.UserID
UserLastName = user.UserLastName
UserLevel = user.UserLevel
UserMiddleInitial = user.UserMiddleInitial
UserName = user.UserName
UserPassword = user.UserPassword
UserPreviouslyLoggedIn = user.UserPreviouslyLoggedIn
}
let FromF (camelTypeF:Func<string,obj option>) =
{
IsLockedOut =
match camelTypeF.Invoke "IsLockedOut" with
|Some x -> Convert.ToBoolean x
|None -> Unchecked.defaultof<_>
LoginAttempts =
match camelTypeF.Invoke "LoginAttempts" with
|Some x -> Convert.ToInt32 x
|None -> Unchecked.defaultof<_>
RcopiaID =
match camelTypeF.Invoke "RcopiaID" with
|Some x -> Convert.ToString x
|None -> Unchecked.defaultof<_>
ResetPassword =
match camelTypeF.Invoke "ResetPassword" with
|Some x -> Convert.ToBoolean x
|None -> Unchecked.defaultof<_>
UserFacilityID =
match camelTypeF.Invoke "UserFacilityID" with
|Some x -> Convert.ToInt32 x
|None -> Unchecked.defaultof<_>
UserFirstName =
match camelTypeF.Invoke "UserFirstName" with
|Some x -> Convert.ToString x
|None -> Unchecked.defaultof<_>
UserID =
match camelTypeF.Invoke "UserID" with
|Some x -> Convert.ToInt32 x
|None -> Unchecked.defaultof<_>
UserLastName =
match camelTypeF.Invoke "UserLastName" with
|Some x -> Convert.ToString x
|None -> Unchecked.defaultof<_>
UserLevel =
match camelTypeF.Invoke "UserLevel" with
|Some x -> Convert.ToInt32 x
|None -> Unchecked.defaultof<_>
UserMiddleInitial =
match camelTypeF.Invoke "UserMiddleInitial" with
|Some x -> Convert.ToString x
|None -> Unchecked.defaultof<_>
UserName =
match camelTypeF.Invoke "UserName" with
|Some x -> Convert.ToString x
|None -> Unchecked.defaultof<_>
UserPassword =
match camelTypeF.Invoke "UserPassword" with
|Some x -> Convert.ToString x
|None -> Unchecked.defaultof<_>
UserPreviouslyLoggedIn =
match camelTypeF.Invoke "UserPreviouslyLoggedIn" with
|Some x -> Convert.ToBoolean x
|None -> Unchecked.defaultof<_>
}
let inline toRecordStp (user: ^a) =
{
IsLockedOut = (^a: (member IsLockedOut: _) user)
LoginAttempts = (^a: (member LoginAttempts: _) user)
RcopiaID = (^a: (member RcopiaID: _) user)
ResetPassword = (^a: (member ResetPassword: _) user)
UserFacilityID = (^a: (member UserFacilityID: _) user)
UserFirstName = (^a: (member UserFirstName: _) user)
UserID = (^a: (member UserID: _) user)
UserLastName = (^a: (member UserLastName: _) user)
UserLevel = (^a: (member UserLevel: _) user)
UserMiddleInitial = (^a: (member UserMiddleInitial: _) user)
UserName = (^a: (member UserName: _) user)
UserPassword = (^a: (member UserPassword: _) user)
UserPreviouslyLoggedIn = (^a: (member UserPreviouslyLoggedIn: _) user)
}
let createInsert (r:IUser) =
let quoted s = "'" + s + "'"
[
"IsLockedOut", r.IsLockedOut |> string |> quoted
"LoginAttempts", r.LoginAttempts |> string
"RcopiaID", if String.IsNullOrEmpty r.RcopiaID then "null" else quoted r.RcopiaID
"ResetPassword", r.ResetPassword |> string |> quoted
"UserFacilityID", r.UserFacilityID |> string
"UserFirstName", if String.IsNullOrEmpty r.UserFirstName then "null" else quoted r.UserFirstName
"UserLastName", if String.IsNullOrEmpty r.UserLastName then "null" else quoted r.UserLastName
"UserLevel", r.UserLevel |> string
"UserMiddleInitial", if String.IsNullOrEmpty r.UserMiddleInitial then "null" else quoted r.UserMiddleInitial
"UserName", if String.IsNullOrEmpty r.UserName then "null" else quoted r.UserName
"UserPassword", if String.IsNullOrEmpty r.UserPassword then "null" else quoted r.UserPassword
"UserPreviouslyLoggedIn", r.UserPreviouslyLoggedIn |> string |> quoted
]
|> fun pairs -> sprintf "insert into dbo.Users(%s) values (%s)" (String.Join(",", pairs |> Seq.map fst )) (String.Join(",", pairs |> Seq.map snd))
/// 13 properties
type UserN (model:UserRecord) =
let propertyChanged = new Event<_, _>()
let mutable isLockedOut = model.IsLockedOut
let mutable loginAttempts = model.LoginAttempts
let mutable rcopiaID = model.RcopiaID
let mutable resetPassword = model.ResetPassword
let mutable userFacilityID = model.UserFacilityID
let mutable userFirstName = model.UserFirstName
let mutable userID = model.UserID
let mutable userLastName = model.UserLastName
let mutable userLevel = model.UserLevel
let mutable userMiddleInitial = model.UserMiddleInitial
let mutable userName = model.UserName
let mutable userPassword = model.UserPassword
let mutable userPreviouslyLoggedIn = model.UserPreviouslyLoggedIn
interface IUser with
/// bit (1) not null
member x.IsLockedOut with get () = x.IsLockedOut
/// int (4) not null
member x.LoginAttempts with get () = x.LoginAttempts
/// varchar (50) null
member x.RcopiaID with get () = x.RcopiaID
/// bit (1) not null
member x.ResetPassword with get () = x.ResetPassword
/// int (4) not null
member x.UserFacilityID with get () = x.UserFacilityID
/// varchar (50) not null
member x.UserFirstName with get () = x.UserFirstName
/// int (4) not null
member x.UserID with get () = x.UserID
/// varchar (50) not null
member x.UserLastName with get () = x.UserLastName
/// int (4) not null
member x.UserLevel with get () = x.UserLevel
/// varchar (1) null
member x.UserMiddleInitial with get () = x.UserMiddleInitial
/// varchar (50) null
member x.UserName with get () = x.UserName
/// varchar (50) not null
member x.UserPassword with get () = x.UserPassword
/// bit (1) not null
member x.UserPreviouslyLoggedIn with get () = x.UserPreviouslyLoggedIn
interface IUserRW with
/// bit (1) not null
member x.IsLockedOut with get () = x.IsLockedOut and set v = x.IsLockedOut <- v
/// int (4) not null
member x.LoginAttempts with get () = x.LoginAttempts and set v = x.LoginAttempts <- v
/// varchar (50) null
member x.RcopiaID with get () = x.RcopiaID and set v = x.RcopiaID <- v
/// bit (1) not null
member x.ResetPassword with get () = x.ResetPassword and set v = x.ResetPassword <- v
/// int (4) not null
member x.UserFacilityID with get () = x.UserFacilityID and set v = x.UserFacilityID <- v
/// varchar (50) not null
member x.UserFirstName with get () = x.UserFirstName and set v = x.UserFirstName <- v
/// int (4) not null
member x.UserID with get () = x.UserID and set v = x.UserID <- v
/// varchar (50) not null
member x.UserLastName with get () = x.UserLastName and set v = x.UserLastName <- v
/// int (4) not null
member x.UserLevel with get () = x.UserLevel and set v = x.UserLevel <- v
/// varchar (1) null
member x.UserMiddleInitial with get () = x.UserMiddleInitial and set v = x.UserMiddleInitial <- v
/// varchar (50) null
member x.UserName with get () = x.UserName and set v = x.UserName <- v
/// varchar (50) not null
member x.UserPassword with get () = x.UserPassword and set v = x.UserPassword <- v
/// bit (1) not null
member x.UserPreviouslyLoggedIn with get () = x.UserPreviouslyLoggedIn and set v = x.UserPreviouslyLoggedIn <- v
member x.MakeRecord () =
{
IsLockedOut = x.IsLockedOut
LoginAttempts = x.LoginAttempts
RcopiaID = x.RcopiaID
ResetPassword = x.ResetPassword
UserFacilityID = x.UserFacilityID
UserFirstName = x.UserFirstName
UserID = x.UserID
UserLastName = x.UserLastName
UserLevel = x.UserLevel
UserMiddleInitial = x.UserMiddleInitial
UserName = x.UserName
UserPassword = x.UserPassword
UserPreviouslyLoggedIn = x.UserPreviouslyLoggedIn
}
interface INotifyPropertyChanged with
[<CLIEvent>]
member x.PropertyChanged = propertyChanged.Publish
abstract member RaisePropertyChanged : string -> unit
default x.RaisePropertyChanged(propertyName : string) = propertyChanged.Trigger(x, PropertyChangedEventArgs(propertyName))
abstract member SetAndNotify<'t> : string * 't byref * 't -> bool
default x.SetAndNotify<'t> (propertyName, field: 't byref, value:'t) =
if obj.ReferenceEquals(box field,box value) then false
else
field <- value
x.RaisePropertyChanged(propertyNam)
true
abstract member SetAndNotify<'t,'b> : string * 'b * 't Action * 't -> bool
default x.SetAndNotify<'t,'b> (propertyName, baseValue:'b, baseSetter: 't Action, value:'t) =
if obj.ReferenceEquals(box baseValue,box value) then false
else
baseSetter.Invoke value
x.RaisePropertyChanged(propertyName)
true
/// bit (1) not null
member x.IsLockedOut
with get() = isLockedOut
and set v =
isLockedOut <- v
x.RaisePropertyChanged "IsLockedOut"
/// int (4) not null
member x.LoginAttempts
with get() = loginAttempts
and set v =
loginAttempts <- v
x.RaisePropertyChanged "LoginAttempts"
/// varchar (50) null
member x.RcopiaID
with get() = rcopiaID
and set v =
rcopiaID <- v
x.RaisePropertyChanged "RcopiaID"
/// bit (1) not null
member x.ResetPassword
with get() = resetPassword
and set v =
resetPassword <- v
x.RaisePropertyChanged "ResetPassword"
/// int (4) not null
member x.UserFacilityID
with get() = userFacilityID
and set v =
userFacilityID <- v
x.RaisePropertyChanged "UserFacilityID"
/// varchar (50) not null
member x.UserFirstName
with get() = userFirstName
and set v =
userFirstName <- v
x.RaisePropertyChanged "UserFirstName"
/// int (4) not null
member x.UserID
with get() = userID
and set v =
userID <- v
x.RaisePropertyChanged "UserID"
/// varchar (50) not null
member x.UserLastName
with get() = userLastName
and set v =
userLastName <- v
x.RaisePropertyChanged "UserLastName"
/// int (4) not null
member x.UserLevel
with get() = userLevel
and set v =
userLevel <- v
x.RaisePropertyChanged "UserLevel"
/// varchar (1) null
member x.UserMiddleInitial
with get() = userMiddleInitial
and set v =
userMiddleInitial <- v
x.RaisePropertyChanged "UserMiddleInitial"
/// varchar (50) null
member x.UserName
with get() = userName
and set v =
userName <- v
x.RaisePropertyChanged "UserName"
/// varchar (50) not null
member x.UserPassword
with get() = userPassword
and set v =
userPassword <- v
x.RaisePropertyChanged "UserPassword"
/// bit (1) not null
member x.UserPreviouslyLoggedIn
with get() = userPreviouslyLoggedIn
and set v =
userPreviouslyLoggedIn <- v
x.RaisePropertyChanged "UserPreviouslyLoggedIn"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment