Skip to content

Instantly share code, notes, and snippets.

@ImaginaryDevelopment
Created February 3, 2016 15:05
Show Gist options
  • Save ImaginaryDevelopment/f08bc70e8e3f9fa7c9db to your computer and use it in GitHub Desktop.
Save ImaginaryDevelopment/f08bc70e8e3f9fa7c9db to your computer and use it in GitHub Desktop.
Proper architecture attempt
namespace Project.Schema
open System
open System.Runtime.CompilerServices
open System.Collections.Generic
// http://blogs.msdn.com/b/jaredpar/archive/2010/07/27/converting-system-func-lt-t1-tn-gt-to-fsharpfunc-lt-t-tresult-gt.aspx
[<Extension>]
type public FSharpFuncUtil =
[<Extension>]
static member ToFSharpFunc<'a,'b> (func:Converter<'a,'b>) = func.Invoke
[<Extension>]
static member ToFSharpFunc<'a,'b> (func:Func<'a,'b>) = fun x -> func.Invoke x
[<Extension>]
static member ToFSharpFunc<'a,'b,'c> (func:Func<'a,'b,'c>) = fun x y -> func.Invoke (x,y)
[<Extension>]
static member ToFSharpFunc<'a,'b,'c,'d> (func:Func<'a,'b,'c,'d>) = fun x y z -> func.Invoke (x,y,z)
[<Extension>]
static member ToFSharpAct<'a> (act: Action<'a>) = fun x -> act.Invoke(x)
[<Extension>]
static member ToFSharpAct<'a,'b> (act: Action<'a,'b>) = fun x y -> act.Invoke(x,y)
static member Create<'a,'b> (func:Func<'a,'b>) = FSharpFuncUtil.ToFSharpFunc func
static member Create<'a,'b,'c> (func:Func<'a,'b,'c>) = FSharpFuncUtil.ToFSharpFunc func
static member Create<'a,'b,'c,'d> (func:Func<'a,'b,'c,'d>) = FSharpFuncUtil.ToFSharpFunc func
module Project.Domain.Accounting
// business logic/rules assembly/project
// domain shouldn't depend on something with Entity props, and should be the heart of the app
type Patient = {AccountId: int<AccountId>; ForeignEhrId:int; RCopiaId: string}
type PatientInfo = {AccountId: int<AccountId>;PatientId:int<PatientId>; LastName:string; FirstName:string;GuarantorId:int<PatientId> option}
// create patient, patient info, and patient account
let createPatient patient (patientInfo:PatientInfo) (getAccountId: _ -> _) (savePatientAccount: _ -> int<AccountId>) (savePatient: _ -> int<PatientId>) (savePatientInfo: _ -> int<PatientInfoId>) (updatePatientAccount: _ -> _ -> unit) =
let patientAccountId,patientAccount =
match patientInfo.GuarantorId with
| Some guarantorId ->
getAccountId guarantorId, None
| None ->
// create patientAccount pass default for entity identifier, there isn't a valid one yet
let patientAccount = Account.createPatientAccount Unchecked.defaultof<_> patientInfo.LastName patientInfo.FirstName
savePatientAccount patientAccount, Some patientAccount
// create patient // derived from argument
let patientId = savePatient {patient with Patient.AccountId = patientAccountId}
// createPatientInfo // implied by argument, just needs saving?
let patientInfo = {patientInfo with PatientId = patientId; AccountId = patientAccountId}
let patientAccount =
match patientAccount with
| Some patientAccount -> // update the Name
let patientAccount = {patientAccount with Name = Account.createPatientAccountName patientId patientInfo.LastName patientInfo.FirstName }
patientAccount
|> updatePatientAccount patientAccountId
Some patientAccount
| None -> None
//create patientInfo
let patientInfoId = savePatientInfo patientInfo
patientAccountId,patientAccount,patientInfoId, patientInfo
// dal layer
namespace Project.Foundation.DataModels
{
public static class PatientDataAccess
{
static Project.Schema.Patients.PatientReturnDataModel CreatePatient(PatientDataModel patient, Connector cn)
{
if (patient.PatientID != 0)
throw new ArgumentOutOfRangeException("patient", "PatientID should have been 0, but was " + patient.PatientID);
Func<int, int> getPatientAccountId = patientId =>
{
return Project.Dal.AdoHelper.ExecuteScalarInt("select "
+ nameof(Project.Schema.DataModels.Patients.PatientRecord.AccountID)
+ " from " + Project.Schema.DataModels.Patients.PatientHelpers.Meta.tableName
+ " where " + nameof(Project.Schema.DataModels.Patients.PatientRecord.PatientID)
+ " = " + patientId, CommandType.Text, cn, null);
};
// there is no way at compile time to ensure I'm reading ALL fields from the domain
// I could have provided a default value with the intention to come back for that feature/data item
// Could have passed something from the ui data model that is now owned/handled in the domain and wasn't previously
Func<Project.Domain.Accounting.Patient, int> savePatient = p =>
{
var @params = new Dictionary<string, object>
{
["@PatientID"] = 0,
["@PatientInfoID"] = 0,
["@ForeignEHRID"] = patient.ForeignEHRID,
["@RcopiaID"] = patient.RcopiaID != null ? (object)patient.RcopiaID : System.DBNull.Value,
["@AccountID"] = p.AccountId
};
//AppDb is a typeprovider so I can compile-time ensure the sproc actually exists
return Project.Dal.AdoHelper.ExecuteScalarIdentity(nameof(AppDb.UspPatientsInsUpd), CommandType.StoredProcedure, cn, @params);
};
Func<Project.Domain.Accounting.PatientInfo, int> savePatientInfo = pi =>
{
return UpdatePatientInfo(patient, cn, pi);
};
var getPatientAccountId2 = Project.Schema.FSharpFuncUtil.ToFSharpFunc(getPatientAccountId);
var insertAccount = Project.Schema.FSharpFuncUtil.ToFSharpFunc(DataAccess.AccountDataAccess.CreateInsertAccountFunc(cn));
var savePatient2 = Project.Schema.FSharpFuncUtil.ToFSharpFunc(savePatient);
var savePatientInfo2 = Project.Schema.FSharpFuncUtil.ToFSharpFunc(savePatientInfo);
var updateAccount = Project.Schema.FSharpFuncUtil.ToFSharpAct(DataAccess.AccountDataAccess.CreateUpdateAccountFunc(cn));
var result = Project.Domain.Accounting.createPatient(
new Project.Domain.Accounting.Patient(0, patient.ForeignEHRID, patient.RcopiaID),
new Project.Domain.Accounting.PatientInfo(0, 0, patient.LastName, patient.FirstName, patient.GuarantorID > 0 ? Microsoft.FSharp.Core.FSharpOption<int>.Some(patient.GuarantorID) : Microsoft.FSharp.Core.FSharpOption<int>.None), getPatientAccountId2, insertAccount, savePatient2, savePatientInfo2, updateAccount);
patient.AccountID = result.Item1;
patient.PatientID = result.Item4.PatientId;
patient.PatientInfoID = result.Item3;
if (patient.PatientID == 0)
throw new InvalidOperationException("patientId wasn't set");
Project.Dal.AdoHelper.ExecuteNonQuery($"update patients set patientinfoid = {patient.PatientInfoID} where patientid = {patient.PatientID}", CommandType.Text, cn, null);
return new Project.Schema.Patients.PatientReturnDataModel(patientId: patient.PatientID, patientInfoId: patient.PatientInfoID);
}
}
}
// ui-specific class
using System;
using System.Drawing;
using System.Text;
using System.Text.RegularExpressions;
namespace Project.Foundation.DataModels
{
public class PatientDataModel : Project.Schema.DataModels.PatientsInfoes.PatientsInfoN
{
int _ForeignEHRID;
string _RcopiaID;
string _DOBAGE;
byte[] _FrontScanData;
byte[] _BackScanData;
byte[] _FaceScanData;
DateTime? _NextAppointment;
DateTime? _LastAppointment;
Image _BackScan;
Image _FaceScan;
Image _FrontScan;
Guid _PatientGuid;
public PatientDataModel() : this(Project.Schema.DataModels.PatientsInfoes.PatientsInfoRecord.Zero(), new Project.Dal.Patients.PatientCoreInfo(null, null, null), 0) { }
//alternate constructor for other use cases of the same type
public PatientDataModel(Project.Schema.DataModels.PatientsInfoes.PatientsInfoRecord r, Project.Dal.Patients.PatientCoreInfo p, int age) : base(r)
{
if (string.IsNullOrEmpty(this.DriversLicenseExpiration))
this.DriversLicenseExpiration = "N/A";
if (string.IsNullOrEmpty(this.Ethnicity))
this.Ethnicity = "Non-hispanic/latino";
if (string.IsNullOrEmpty(this.MaritalStatus))
this.MaritalStatus = "Refused";
this._DOBAGE = r.DOB.ToString("d") + "(" + age + "yr)";
this._PatientGuid = p.PatientGuid.GetValueOrDefault();
this._RcopiaID = p.RcopiaID;
this._ForeignEHRID = p.ForeignEhrId.GetValueOrDefault();
this.IsDirty = false;
}
public new bool IsITIN
{
get { return base.IsITIN.GetValueOrDefault() == 1; }
set { this.SetAndNotify(nameof(this.IsITIN), base.IsITIN, v => base.IsITIN = v, value ? 1 : 0); }
}
public new bool IsNoneRefused
{
get { return base.IsNoneRefused.GetValueOrDefault() == 1; }
set { this.SetAndNotify(nameof(this.IsNoneRefused), base.IsNoneRefused, v => base.IsNoneRefused = v, value ? 1 : 0); }
}
public new string Address1
{
get { return base.Address1; }
set { this.SetAndNotify(nameof(this.Address1), base.Address1, v => base.Address1 = v, value != null ? value.ToUpperInvariant() : value); }
}
public new string Address2
{
get { return base.Address2; }
set { this.SetAndNotify(nameof(this.Address2), base.Address2, v => base.Address2 = v, value != null ? value.ToUpperInvariant() : value); }
}
public new string City
{
get { return base.City; }
set { this.SetAndNotify(nameof(this.City), base.City, v => base.City = v, value != null ? value.ToUpperInvariant() : value); }
}
public new string State
{
get { return base.State; }
set { this.SetAndNotify(nameof(this.State), base.State, v => base.State = v, value != null ? value.ToUpperInvariant() : value); }
}
public new bool PrimaryPhoneIsMobile
{
get { return base.PrimaryPhoneIsMobile.GetValueOrDefault() == 1; }
set { this.SetAndNotify(nameof(this.PrimaryPhoneIsMobile), base.PrimaryPhoneIsMobile, v => base.PrimaryPhoneIsMobile = v, value ? 1 : 0); }
}
public new bool SecondaryPhoneIsMobile
{
get { return base.SecondaryPhoneIsMobile.GetValueOrDefault() == 1; }
set { this.SetAndNotify(nameof(this.SecondaryPhoneIsMobile), base.SecondaryPhoneIsMobile, v => base.SecondaryPhoneIsMobile = v, value ? 1 : 0); }
}
public new bool PrimaryPhoneCanLeaveMessage
{
get { return base.PrimaryPhoneCanLeaveMessage.GetValueOrDefault() == 1; }
set { this.SetAndNotify(nameof(this.PrimaryPhoneCanLeaveMessage), base.PrimaryPhoneCanLeaveMessage, v => base.PrimaryPhoneCanLeaveMessage = v, value ? 1 : 0); }
}
public new bool SecondaryPhoneCanLeaveMessage
{
get { return base.SecondaryPhoneCanLeaveMessage.GetValueOrDefault() == 1; }
set { this.SetAndNotify(nameof(this.SecondaryPhoneCanLeaveMessage), base.SecondaryPhoneCanLeaveMessage, v => base.SecondaryPhoneCanLeaveMessage = v, value ? 1 : 0); }
}
public new string EmailAddress
{
get { return base.EmailAddress; }
set { this.SetAndNotify(nameof(this.EmailAddress), base.EmailAddress, v => base.EmailAddress = v, value != null ? value.ToUpperInvariant() : value); }
}
/// <summary>
/// If Patient is a minor this would be the patientId of the guarantor
/// </summary>
public new int GuarantorID
{
get { return base.GuarantorID.GetValueOrDefault(); }
set { this.SetAndNotify(nameof(this.GuarantorID), base.GuarantorID, v => base.GuarantorID = v, (int?)value); }
}
#region Emergency Contact Info
public new string EmergencyContactFirstName
{
get { return base.EmergencyContactFirstName; }
set { this.SetAndNotify(nameof(this.EmergencyContactFirstName), base.EmergencyContactFirstName, v => base.EmergencyContactFirstName = v, value.ToUpperInvariant()); }
}
public new string EmergencyContactLastName
{
get { return base.EmergencyContactLastName; }
set { this.SetAndNotify(nameof(this.EmergencyContactLastName), base.EmergencyContactLastName, v => base.EmergencyContactLastName = v, value.ToUpperInvariant()); }
}
public new string EmergencyContactAddress1
{
get { return base.EmergencyContactAddress1; }
set { this.SetAndNotify(nameof(this.EmergencyContactAddress1), base.EmergencyContactAddress1, v => base.EmergencyContactAddress1 = v, value.ToUpperInvariant()); }
}
public new string EmergencyContactAddress2
{
get { return base.EmergencyContactAddress2; }
set { this.SetAndNotify(nameof(this.EmergencyContactAddress2), base.EmergencyContactAddress2, v => base.EmergencyContactAddress2 = v, value.ToUpperInvariant()); }
}
public new string EmergencyContactAddressCity
{
get { return base.EmergencyContactAddressCity; }
set { this.SetAndNotify(nameof(this.EmergencyContactAddressCity), base.EmergencyContactAddressCity, v => base.EmergencyContactAddressCity = v, value.ToUpperInvariant()); }
}
public new string AlertMessage
{
get { return base.AlertMessage; }
set { this.SetAndNotify(nameof(this.AlertMessage), base.AlertMessage, v => base.AlertMessage = v, value.ToUpperInvariant()); }
}
public new string EmergencyContactAddressState
{
get { return base.EmergencyContactAddressState; }
set { this.SetAndNotify(nameof(this.EmergencyContactAddressState), base.EmergencyContactAddressState, v => base.EmergencyContactAddressState = v, value.ToUpperInvariant()); }
}
public new bool EmergencyContactPrimaryPhoneIsMobile
{
get { return base.EmergencyContactPrimaryPhoneIsMobile.GetValueOrDefault() == 1; }
set { this.SetAndNotify(nameof(this.EmergencyContactPrimaryPhoneIsMobile), base.EmergencyContactPrimaryPhoneIsMobile, v => base.EmergencyContactPrimaryPhoneIsMobile = v, value ? 1 : 0); }
}
public new bool EmergencyContactSecondaryPhoneIsMobile
{
get { return base.EmergencyContactSecondaryPhoneIsMobile.GetValueOrDefault() == 1; }
set { this.SetAndNotify(nameof(this.EmergencyContactSecondaryPhoneIsMobile), base.EmergencyContactSecondaryPhoneIsMobile, v => base.EmergencyContactSecondaryPhoneIsMobile = v, value ? 1 : 0); }
}
#endregion
public new int PCP
{
get { return string.IsNullOrEmpty(base.PCP) ? 0 : int.Parse(base.PCP); }
set { this.SetAndNotify(nameof(this.PCP), base.PCP, v => base.PCP = v, value.ToString()); }
}
#region Employer Info
public new bool EmploymentStatus
{
get { return base.EmploymentStatus == 1; }
set { this.SetAndNotify(nameof(this.EmploymentStatus), base.EmploymentStatus, v => base.EmploymentStatus = v, value ? 1 : 0); }
}
public new string EmployerName
{
get { return base.EmployerName; }
set { this.SetAndNotify(nameof(this.EmployerName), base.EmployerName, v => base.EmployerName = v, value.ToUpperInvariant()); }
}
public new string EmployerAddress1
{
get { return base.EmployerAddress1; }
set { this.SetAndNotify(nameof(this.EmployerAddress1), base.EmployerAddress1, v => base.EmployerAddress1 = v, value.ToUpperInvariant()); }
}
public new string EmployerAddress2
{
get { return base.EmployerAddress2; }
set { this.SetAndNotify(nameof(this.EmployerAddress2), base.EmployerAddress2, v => base.EmployerAddress2 = v, value.ToUpperInvariant()); }
}
public new string EmployerCity
{
get { return base.EmployerCity; }
set { this.SetAndNotify(nameof(this.EmployerCity), base.EmployerCity, v => base.EmployerCity = v, value.ToUpperInvariant()); }
}
public new string EmployerState
{
get { return base.EmployerState; }
set { this.SetAndNotify(nameof(this.EmployerState), base.EmployerState, v => base.EmployerState = v, value.ToUpperInvariant()); }
}
public new string EmployerOccupation
{
get { return base.EmployerOccupation; }
set { this.SetAndNotify(nameof(this.EmployerOccupation), base.EmployerOccupation, v => base.EmployerOccupation = v, value.ToUpperInvariant()); }
}
public new string EmployerTitle
{
get { return base.EmployerTitle; }
set { this.SetAndNotify(nameof(this.EmployerTitle), base.EmployerTitle, v => base.EmployerTitle = v, value.ToUpperInvariant()); }
}
public new string EmployerSupervisor
{
get { return base.EmployerSupervisor; }
set { this.SetAndNotify(nameof(this.EmployerSupervisor), base.EmployerSupervisor, v => base.EmployerSupervisor = v, value.ToUpperInvariant()); }
}
#endregion
public new int PatientID
{
get { return base.PatientID.GetValueOrDefault(); }
set
{
base.PatientID = value;
RaisePropertyChanged(nameof(IsFirstEntry));
}
}
public new int LanguageID
{
get { return base.LanguageID.GetValueOrDefault(); }
set
{
base.LanguageID = value == 0 ? (int?)null : value;
}
}
public new string FirstName
{
get { return base.FirstName; }
set
{
if (this.SetAndNotify(nameof(this.FirstName), base.FirstName, v => base.FirstName = v, value != null ? value.ToUpperInvariant() : value))
this.RaisePropertyChanged(nameof(this.LastNameFirstName));
}
}
public new string MiddleInitial
{
get { return base.MiddleInitial; }
set { this.SetAndNotify(nameof(this.MiddleInitial), base.MiddleInitial, v => base.MiddleInitial = v, value != null ? value.ToUpperInvariant() : value); }
}
public new string LastName
{
get { return base.LastName; }
set
{
if (this.SetAndNotify(nameof(this.LastName), base.LastName, v => base.LastName = v, value != null ? value.ToUpperInvariant() : value))
this.RaisePropertyChanged(nameof(this.LastNameFirstName));
}
}
public new string Gender
{
get { return base.Gender; }
set { this.SetAndNotify(nameof(this.Gender), base.Gender, v => base.Gender = v, value != null ? value.ToUpperInvariant() : value); }
}
public new DateTime? DOB
{
get { return base.DOB == default(DateTime) ? (DateTime?)null : base.DOB; }
set { base.DOB = value.GetValueOrDefault(); }
}
public new int PatientIdentificationID
{
get { return base.PatientIdentificationID.GetValueOrDefault(); }
set { base.PatientIdentificationID = value == 0 ? (int?)null : value; ; }
}
public new string PreferredName
{
get { return base.PreferredName; }
set { this.SetAndNotify(nameof(this.PreferredName), base.PreferredName, v => base.PreferredName = v, value.ToUpperInvariant()); }
}
public new string Note
{
get { return base.Note; }
set { this.SetAndNotify(nameof(this.Note), base.Note, v => base.Note = v, value.ToUpperInvariant()); }
}
public new int LastUpdateUser
{
get { return base.LastUpdateUser.GetValueOrDefault(); }
set
{
if (this.SetAndNotify(nameof(this.LastUpdateUser), base.LastUpdateUser, v => base.LastUpdateUser = v, value == 0 ? (int?)null : value))
RaisePropertyChanged(nameof(IsFirstEntry));
}
}
public byte[] FrontScanData
{
get { return _FrontScanData; }
set { this.SetAndNotify(nameof(this.FrontScanData), ref _FrontScanData, value); }
}
public int ForeignEHRID
{
get { return _ForeignEHRID; }
set { this.SetAndNotify(nameof(this.ForeignEHRID), ref _ForeignEHRID, value); }
}
public string RcopiaID
{
get { return _RcopiaID; }
set { this.SetAndNotify(nameof(this.RcopiaID), ref _RcopiaID, value); }
}
public Guid PatientGuid
{
get { return _PatientGuid; }
set { this.SetAndNotify(nameof(this.PatientGuid), ref _PatientGuid, value); }
}
public string DOBAGE
{
get { return _DOBAGE; }
set { this.SetAndNotify(nameof(this.DOBAGE), ref _DOBAGE, value); }
}
public Image FrontScan
{
get { return _FrontScan; }
set { this.SetAndNotify(nameof(this.FrontScan), ref _FrontScan, value); }
}
public byte[] BackScanData
{
get { return _BackScanData; }
set { this.SetAndNotify(nameof(this.BackScanData), ref _BackScanData, value); }
}
public Image BackScan
{
get { return _BackScan; }
set { this.SetAndNotify(nameof(this.BackScan), ref _BackScan, value); }
}
public byte[] FaceScanData
{
get { return _FaceScanData; }
set { this.SetAndNotify(nameof(this.FaceScanData), ref _FaceScanData, value); }
}
public Image FaceScan
{
get { return _FaceScan; }
set { this.SetAndNotify(nameof(this.FaceScan), ref _FaceScan, value); }
}
public string CSZ
{
get
{
string comma = " ";
if (!string.IsNullOrWhiteSpace(this.City) && !string.IsNullOrWhiteSpace(this.State))
comma = ", ";
return this.City + comma + this.State + " " + this.Zip;
}
}
public string XPMPatientID
{
get
{
var builder = new StringBuilder();
builder.Append("XPM");
if (!string.IsNullOrWhiteSpace(Convert.ToString(this.PatientID)))
builder.Append(Convert.ToString(this.PatientID));
return builder.ToString();
}
}
public string LastNameFirstNameMiddleInitialPrinted
{
get
{
var nameBuilder = BuildName(s => " " + s + ".");
return nameBuilder.ToString();
}
}
public string NameAndGender => this.LastNameFirstName + " (" + this.Gender + ")";
public DateTime? NextAppointment
{
get { return _NextAppointment; }
set { this.SetAndNotify(nameof(this.NextAppointment), ref _NextAppointment, value); }
}
public DateTime? LastAppointment
{
get { return _LastAppointment; }
set { this.SetAndNotify(nameof(this.LastAppointment), ref _LastAppointment, value); }
}
public string FormattedPhoneNumber => PrimaryPhone != null ? Regex.Replace(PrimaryPhone, @"(\d{3})(\d{3})(\d{4})", "$1-$2-$3"): null;
public string Formatted_PhoneNumber => PrimaryPhone != null ? Regex.Replace(PrimaryPhone, @"(\d{3})(\d{3})(\d{4})", "($1)$2 $3") : null;
public bool IsDirty { get; set; }
public string LastNameFirstNameDate
{
get
{
var builder = BuildName(s => string.Empty); // no middle initial for this format
if (this.DOB != null)
{
var date = DateTime.Parse(this.DOB.ToString());
builder.Append(" (" + date.ToString("MM/dd/yyyy") + ")");
}
return builder.ToString();
}
}
public string LastNameFirstNameMiddleInitialDate
{
get
{
var nameBuilder = BuildName(s => " " + s);
if (this.DOB != null)
{
var date = DateTime.Parse(this.DOB.ToString());
nameBuilder.Append(" (" + date.ToString("MM/dd/yyyy") + ")");
}
return nameBuilder.ToString();
}
}
public string LastNameFirstNameMiddleInitial
{
get
{
var builder = BuildName(s => " " + s);
return builder.ToString();
}
}
public string LastNameFirstNameDOBGender
{
get
{
var builder = BuildName(s => string.Empty); // no middle initial for this format
if (this.DOB != null)
{
var date = DateTime.Parse(this.DOB.ToString());
builder.Append(" (" + date.ToString("MM/dd/yyyy ") + this.Gender + ")");
}
return builder.ToString();
}
}
public string LastNameFirstName
{
get
{
var builder = BuildName(s => string.Empty); // no middle initial for this format
return builder.ToString();
}
}
StringBuilder BuildName(Func<string, string> middleInitialFormat)
{
var builder = new StringBuilder();
if (!string.IsNullOrWhiteSpace(this.LastName))
builder.Append(this.LastName);
if (!string.IsNullOrWhiteSpace(this.LastName) && !string.IsNullOrWhiteSpace(this.FirstName))
builder.Append(", ");
if (!string.IsNullOrWhiteSpace(this.FirstName))
builder.Append(this.FirstName);
if (!string.IsNullOrWhiteSpace(this.MiddleInitial))
builder.Append(middleInitialFormat(this.MiddleInitial));
return builder;
}
public override string ToString()
{
return BuildName(s => s) + "(" + this.PatientID + ")";
}
public override void RaisePropertyChanged(string propertyName)
{
base.RaisePropertyChanged(propertyName);
this.IsDirty = true;
}
}
}
namespace Project.Schema
[<Measure>] type PatientId
//legacy code base, I'm kind of on the fence with the amount of C# present
// if the measures should be pervasive and are helpful/valuable and should be in any of the non-domain or types
//so not all representations of patient or any other type have measures, besides almost all of the domain logic types/functions
namespace Project.Schema.DataModels.Patients // Generated by T4 in namespace Project.Dal
// types shared between layers, no behaviors, just shapes go here
// something all layers can depend on without taking dependencies on anything platform/ui/dal specific
// this file represents a Project.Schema assembly/project
open System
open System.ComponentModel
open System.Linq.Expressions
open FSharp.NullHelpers
open Project.Schema.Reusable
/// 6 properties
type IPatient =
/// int (4) null
abstract member AccountID:int Nullable with get
/// int (4) null
abstract member ForeignEHRID:int Nullable with get
/// uniqueidentifier (16) null
abstract member PatientGUID:Guid Nullable with get
/// int (4) not null identity
abstract member PatientID:int with get
/// int (4) null
abstract member PatientInfoID:int Nullable with get
/// varchar (50) null
abstract member RcopiaID:string with get
/// 6 properties
type IPatientRW =
inherit IPatient
/// int (4) null
abstract member AccountID:int Nullable with get,set
/// int (4) null
abstract member ForeignEHRID:int Nullable with get,set
/// uniqueidentifier (16) null
abstract member PatientGUID:Guid Nullable with get,set
/// int (4) not null identity
abstract member PatientID:int with get,set
/// int (4) null
abstract member PatientInfoID:int Nullable with get,set
/// varchar (50) null
abstract member RcopiaID:string with get,set
/// 6 properties
[<NoComparison>]
type PatientRecord =
{
/// int (4) null
AccountID:int Nullable
/// int (4) null
ForeignEHRID:int Nullable
/// uniqueidentifier (16) null
PatientGUID:Guid Nullable
/// int (4) not null identity
PatientID:int
/// int (4) null
PatientInfoID:int Nullable
/// varchar (50) null
RcopiaID:string
}
interface IPatient with
member x.AccountID with get () = x.AccountID
member x.ForeignEHRID with get () = x.ForeignEHRID
member x.PatientGUID with get () = x.PatientGUID
member x.PatientID with get () = x.PatientID
member x.PatientInfoID with get () = x.PatientInfoID
member x.RcopiaID with get () = x.RcopiaID
static member Zero () =
{
AccountID = Nullable()
ForeignEHRID = Nullable()
PatientGUID = Nullable()
PatientID = 0
PatientInfoID = Nullable()
RcopiaID = null
}
module PatientHelpers =
open Microsoft.FSharp.Core.Operators.Unchecked
module Meta =
let schemaName = "dbo"
let tableName = "Patients"
let AccountID = "AccountID"
let ForeignEHRID = "ForeignEHRID"
let PatientGUID = "PatientGUID"
let PatientID = "PatientID"
let PatientInfoID = "PatientInfoID"
let RcopiaID = "RcopiaID"
let ToRecord (iPatient:IPatient) =
{
AccountID = iPatient.AccountID
ForeignEHRID = iPatient.ForeignEHRID
PatientGUID = iPatient.PatientGUID
PatientID = iPatient.PatientID
PatientInfoID = iPatient.PatientInfoID
RcopiaID = iPatient.RcopiaID
}
let toRecord (patient:IPatient) =
{
AccountID = patient.AccountID
ForeignEHRID = patient.ForeignEHRID
PatientGUID = patient.PatientGUID
PatientID = patient.PatientID
PatientInfoID = patient.PatientInfoID
RcopiaID = patient.RcopiaID
}
let FromF (camelTypeF:Func<string,obj option>) =
{
AccountID =
match camelTypeF.Invoke "AccountID" with // int Nullable
|Some x -> Nullable (Convert.ToInt32 x )
|None -> Unchecked.defaultof<_>
ForeignEHRID =
match camelTypeF.Invoke "ForeignEHRID" with // int Nullable
|Some x -> Nullable (Convert.ToInt32 x )
|None -> Unchecked.defaultof<_>
PatientGUID =
match camelTypeF.Invoke "PatientGUID" with // Guid Nullable
|Some x -> Nullable (Convert.ToGuid x )
|None -> Unchecked.defaultof<_>
PatientID =
match camelTypeF.Invoke "PatientID" with // int
|Some x -> Convert.ToInt32 x
|None -> Unchecked.defaultof<_>
PatientInfoID =
match camelTypeF.Invoke "PatientInfoID" with // int Nullable
|Some x -> Nullable (Convert.ToInt32 x )
|None -> Unchecked.defaultof<_>
RcopiaID =
match camelTypeF.Invoke "RcopiaID" with // string
|Some x -> Convert.ToString x
|None -> Unchecked.defaultof<_>
}
let inline toRecordStp (patient: ^a) =
{
AccountID = (^a: (member AccountID: _) patient)
ForeignEHRID = (^a: (member ForeignEHRID: _) patient)
PatientGUID = (^a: (member PatientGUID: _) patient)
PatientID = (^a: (member PatientID: _) patient)
PatientInfoID = (^a: (member PatientInfoID: _) patient)
RcopiaID = (^a: (member RcopiaID: _) patient)
}
let createInsert (r:IPatient) =
let quoted (s:string) = "'" + s.Replace("'","''") + "'" //varchar
[
"AccountID", if isNull (box r.AccountID) then "null" else r.AccountID |> string
"ForeignEHRID", if isNull (box r.ForeignEHRID) then "null" else r.ForeignEHRID |> string
"PatientGUID", if isNull (box r.PatientGUID) then "null" else r.PatientGUID |> string |> quoted
"PatientInfoID", if isNull (box r.PatientInfoID) then "null" else r.PatientInfoID |> string
"RcopiaID", if String.IsNullOrEmpty r.RcopiaID then "null" else quoted r.RcopiaID
]
|> fun pairs -> sprintf "insert into dbo.Patients(%s) values (%s)" (String.Join(",", pairs |> Seq.map fst )) (String.Join(",", pairs |> Seq.map snd))
/// 6 properties
type PatientN (model:PatientRecord) = // class for ui inheritance, also implement INPC
let propertyChanged = new Event<_, _>()
let mutable accountID = model.AccountID
let mutable foreignEHRID = model.ForeignEHRID
let mutable patientGUID = model.PatientGUID
let mutable patientID = model.PatientID
let mutable patientInfoID = model.PatientInfoID
let mutable rcopiaID = model.RcopiaID
interface IPatient with
/// int (4) null
member x.AccountID with get () = x.AccountID
/// int (4) null
member x.ForeignEHRID with get () = x.ForeignEHRID
/// uniqueidentifier (16) null
member x.PatientGUID with get () = x.PatientGUID
/// int (4) not null identity
member x.PatientID with get () = x.PatientID
/// int (4) null
member x.PatientInfoID with get () = x.PatientInfoID
/// varchar (50) null
member x.RcopiaID with get () = x.RcopiaID
interface IPatientRW with
/// int (4) null
member x.AccountID with get () = x.AccountID and set v = x.AccountID <- v
/// int (4) null
member x.ForeignEHRID with get () = x.ForeignEHRID and set v = x.ForeignEHRID <- v
/// uniqueidentifier (16) null
member x.PatientGUID with get () = x.PatientGUID and set v = x.PatientGUID <- v
/// int (4) not null identity
member x.PatientID with get () = x.PatientID and set v = x.PatientID <- v
/// int (4) null
member x.PatientInfoID with get () = x.PatientInfoID and set v = x.PatientInfoID <- v
/// varchar (50) null
member x.RcopiaID with get () = x.RcopiaID and set v = x.RcopiaID <- v
member x.MakeRecord () =
{
AccountID = x.AccountID
ForeignEHRID = x.ForeignEHRID
PatientGUID = x.PatientGUID
PatientID = x.PatientID
PatientInfoID = x.PatientInfoID
RcopiaID = x.RcopiaID
}
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(propertyName)
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
/// int (4) null
member x.AccountID
with get() = accountID
and set v =
accountID <- v
x.RaisePropertyChanged "AccountID"
/// int (4) null
member x.ForeignEHRID
with get() = foreignEHRID
and set v =
foreignEHRID <- v
x.RaisePropertyChanged "ForeignEHRID"
/// uniqueidentifier (16) null
member x.PatientGUID
with get() = patientGUID
and set v =
patientGUID <- v
x.RaisePropertyChanged "PatientGUID"
/// int (4) not null identity
member x.PatientID
with get() = patientID
and set v =
patientID <- v
x.RaisePropertyChanged "PatientID"
/// int (4) null
member x.PatientInfoID
with get() = patientInfoID
and set v =
patientInfoID <- v
x.RaisePropertyChanged "PatientInfoID"
/// varchar (50) null
member x.RcopiaID
with get() = rcopiaID
and set v =
rcopiaID <- v
x.RaisePropertyChanged "RcopiaID"
@ImaginaryDevelopment
Copy link
Author

apparently github gists don't care what order you put the files in, it will alphabetize, I meant this to be a proper top-down readable deal. with schema -> domain -> dal/ui. everything can/does depend on schema. everything except schema can/does depend on domain (although I'd prefer to rework it so only composition root does that)

@ImaginaryDevelopment
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment