src/DbColumnInfo.psm1
|
using namespace System.ComponentModel.DataAnnotations.Schema using namespace System.Data using namespace System.Management.Automation using namespace System.Reflection using namespace System.Threading <# .SYNOPSIS Provides information about a database column. #> class DbColumnInfo { <# .SYNOPSIS The nullability context. #> hidden static [ThreadLocal[NullabilityInfoContext]] $NullabilityContext = [ThreadLocal[NullabilityInfoContext]]::new([Func[NullabilityInfoContext]] { [NullabilityInfoContext]::new() }) <# .SYNOPSIS The mapping between common .NET types and data types. #> hidden static [hashtable] $TypeMap = @{ [bool] = [DbType]::Boolean [byte[]] = [DbType]::Binary [byte] = [DbType]::Byte [char] = [DbType]::StringFixedLength [DateOnly] = [DbType]::Date [datetime] = [DbType]::DateTime [DateTimeOffset] = [DbType]::DateTimeOffset [decimal] = [DbType]::Decimal [double] = [DbType]::Double [float] = [DbType]::Single [guid] = [DbType]::Guid [int] = [DbType]::Int32 [long] = [DbType]::Int64 [Nullable[bool]] = [DbType]::Boolean [Nullable[byte]] = [DbType]::Byte [Nullable[char]] = [DbType]::StringFixedLength [Nullable[DateOnly]] = [DbType]::Date [Nullable[datetime]] = [DbType]::DateTime [Nullable[DateTimeOffset]] = [DbType]::DateTimeOffset [Nullable[decimal]] = [DbType]::Decimal [Nullable[double]] = [DbType]::Double [Nullable[float]] = [DbType]::Single [Nullable[guid]] = [DbType]::Guid [Nullable[int]] = [DbType]::Int32 [Nullable[long]] = [DbType]::Int64 [Nullable[sbyte]] = [DbType]::SByte [Nullable[short]] = [DbType]::Int16 [Nullable[TimeOnly]] = [DbType]::Time [Nullable[uint]] = [DbType]::UInt32 [Nullable[ulong]] = [DbType]::UInt64 [Nullable[ushort]] = [DbType]::UInt16 [sbyte] = [DbType]::SByte [short] = [DbType]::Int16 [string] = [DbType]::String [TimeOnly] = [DbType]::Time [uint] = [DbType]::UInt32 [ulong] = [DbType]::UInt64 [ushort] = [DbType]::UInt16 } <# .SYNOPSIS Value indicating whether the column can be read. #> [bool] $CanRead <# .SYNOPSIS Value indicating whether the column can be written to. #> [bool] $CanWrite <# .SYNOPSIS The SQL data type of the column. #> [DbType] $DbType <# .SYNOPSIS Value indicating whether the column value is generated by the database. #> [bool] $IsComputed <# .SYNOPSIS Value indicating whether the column value is generated by the database when a row is inserted. #> [bool] $IsIdentity <# .SYNOPSIS Value indicating whether the column value is nullable. #> [bool] $IsNullable <# .SYNOPSIS The column name. #> [string] $Name <# .SYNOPSIS The type of the column value. #> [Type] $PropertyType <# .SYNOPSIS The property information providing the column metadata. #> hidden [PropertyInfo] $Property <# .SYNOPSIS Creates new column information. .PARAMETER Property The property information providing the column metadata. #> DbColumnInfo([PropertyInfo] $Property) { $this.CanRead = $Property.CanRead $this.CanWrite = $Property.CanWrite $this.Property = $Property $this.PropertyType = $Property.PropertyType $column = [Attribute]::GetCustomAttribute($Property, [ColumnAttribute]) $this.Name = ${column}?.Name ?? $Property.Name $dataType = [DbType]::Object $this.DbType = switch ($true) { ([string]::IsNullOrWhiteSpace(${column}?.TypeName)) { [DbColumnInfo]::TypeMap[$property.PropertyType] ?? [DbType]::Object; break } ([Enum]::TryParse([DbType], $column.TypeName, $true, [ref] $dataType)) { $dataType; break } default { [DbType]::Object } } $databaseGeneratedOption = [Attribute]::GetCustomAttribute($Property, [DatabaseGeneratedAttribute])?.DatabaseGeneratedOption ?? [DatabaseGeneratedOption]::None $this.IsComputed = $databaseGeneratedOption -ne [DatabaseGeneratedOption]::None $this.IsIdentity = $databaseGeneratedOption -eq [DatabaseGeneratedOption]::Identity $this.IsNullable = (-not [Attribute]::IsDefined($Property, [ValidateNotNullAttribute])) -and ` (($null -ne [Nullable]::GetUnderlyingType($Property.PropertyType)) -or ([DbColumnInfo]::NullabilityContext.Value.Create($Property).WriteState -ne [NullabilityState]::NotNull)) } <# .SYNOPSIS Gets the property value of a specified object. .PARAMETER Instance The object whose property value will be returned. .OUTPUTS The property value of the specified object. #> [object] GetValue([object] $Instance) { return $this.Property.GetValue($Instance) } <# .SYNOPSIS Sets the property value of a specified object. .PARAMETER Instance The object whose property value will be set. .PARAMETER Value The new property value. #> [void] SetValue([object] $Instance, [object] $Value) { $this.Property.SetValue($Instance, $Value) } } |