Simplified MySqlColumn by removing Default and Nullable. Added support for built in Nullable types. Bumped package version to 1.1.0

This commit is contained in:
MattMo 2023-02-22 08:06:42 -08:00
parent 7595acb740
commit 15e51b7a42
6 changed files with 102 additions and 49 deletions

View File

@ -10,19 +10,22 @@ namespace MontoyaTech.MySqlPlus.Example
[MySqlRowIndex("year", "year")] [MySqlRowIndex("year", "year")]
public class Car public class Car
{ {
[MySqlColumn(Id = true, Name = "id", PrimaryKey = true, AutoIncrement = true, Nullable = false)] [MySqlColumn(Id = true, Name = "id", PrimaryKey = true, AutoIncrement = true)]
public ulong Id = 0; public ulong Id = 0;
[MySqlColumn("make")] [MySqlColumn("make")]
public string Make = null; public string Make = null;
[MySqlColumn("model", Nullable = false, Type = "VARCHAR(255)")] [MySqlColumn("model", Type = "VARCHAR(255)")]
public string Model = "Unknown"; public string Model = "Unknown";
[MySqlColumn("year", Nullable = false)] [MySqlColumn("year")]
public uint Year = 0; public uint Year = 0;
[MySqlColumn("dateCreated", typeof(DateTimeToUnixConverter), DefaultValue = 0, Nullable = false)] [MySqlColumn("compact")]
public bool? Compact = null;
[MySqlColumn("dateCreated", typeof(DateTimeToUnixConverter), DefaultValue = 0)]
public DateTime DateCreated = DateTime.UtcNow; public DateTime DateCreated = DateTime.UtcNow;
} }
@ -30,18 +33,21 @@ namespace MontoyaTech.MySqlPlus.Example
{ {
var session = new MySqlSession(""); var session = new MySqlSession("");
if (session.TableExists<Car>())
session.DeleteTable<Car>();
session.CreateTable<Car>(); session.CreateTable<Car>();
session.DeleteAll<Car>(); session.DeleteAll<Car>();
session.Insert(new Car() { Make = "Chevy", Model = "Camaro", Year = 2011 }); session.Insert(new Car() { Make = "Chevy", Model = "Camaro", Year = 2011, Compact = true });
session.Insert(new Car() { Make = "GMC", Model = "Sierra", Year = 2000 }); session.Insert(new Car() { Make = "GMC", Model = "Sierra", Year = 2000 });
var cars = session.GetAll<Car>(); var cars = session.GetAll<Car>();
foreach (var car in cars) foreach (var car in cars)
Console.WriteLine($"Make: {car.Make}, Model: {car.Model}, Year: {car.Year}, DateCreated: {car.DateCreated}"); Console.WriteLine($"Make: {car.Make}, Model: {car.Model}, Year: {car.Year}, Compact: {car.Compact}, DateCreated: {car.DateCreated}");
cars[0].Make = "test"; cars[0].Make = "test";

View File

@ -41,16 +41,6 @@ namespace MontoyaTech.MySqlPlus
/// </summary> /// </summary>
public bool AutoIncrement = false; public bool AutoIncrement = false;
/// <summary>
/// Whether or not this column can be null, default is true.
/// </summary>
public bool Nullable = true;
/// <summary>
/// Whether or not this column has a default value, default is true.
/// </summary>
public bool Default = true;
/// <summary> /// <summary>
/// An overrided default value for this column if set, default is null. /// An overrided default value for this column if set, default is null.
/// </summary> /// </summary>

View File

@ -20,13 +20,13 @@ namespace MontoyaTech.MySqlPlus
/// </summary> /// </summary>
/// <typeparam name="T"></typeparam> /// <typeparam name="T"></typeparam>
/// <param name="row"></param> /// <param name="row"></param>
/// <param name="idField"></param> /// <param name="field"></param>
/// <param name="idColumn"></param> /// <param name="idColumn"></param>
public static bool GetMySqlId<T>(this T row, out FieldInfo idField, out MySqlColumn idColumn) public static bool GetMySqlId<T>(this T row, out FieldInfo field, out MySqlColumn idColumn)
{ {
var type = typeof(T); var type = typeof(T);
return GetMySqlId(type, out idField, out idColumn); return GetMySqlId(type, out field, out idColumn);
} }
/// <summary> /// <summary>
@ -34,12 +34,12 @@ namespace MontoyaTech.MySqlPlus
/// whether or not we found it. /// whether or not we found it.
/// </summary> /// </summary>
/// <param name="type"></param> /// <param name="type"></param>
/// <param name="idField"></param> /// <param name="field"></param>
/// <param name="idColumn"></param> /// <param name="idColumn"></param>
/// <returns></returns> /// <returns></returns>
public static bool GetMySqlId(this Type type, out FieldInfo idField, out MySqlColumn idColumn) public static bool GetMySqlId(this Type type, out FieldInfo field, out MySqlColumn idColumn)
{ {
idField = null; field = null;
idColumn = null; idColumn = null;
@ -54,7 +54,7 @@ namespace MontoyaTech.MySqlPlus
if (column != null && column.Id) if (column != null && column.Id)
{ {
idField = fields[i]; field = fields[i];
idColumn = column; idColumn = column;
return true; return true;
@ -78,9 +78,13 @@ namespace MontoyaTech.MySqlPlus
if (column.Converter != null) if (column.Converter != null)
return column.Converter.CreateInstance<MySqlColumnConverter>().ConvertToType; return column.Converter.CreateInstance<MySqlColumnConverter>().ConvertToType;
var code = Type.GetTypeCode(field.FieldType); var typeCode = Type.GetTypeCode(field.FieldType);
switch (code) //If the field type is a nullable, get the actual field type.
if (field.FieldType.IsNullable())
typeCode = Type.GetTypeCode(Nullable.GetUnderlyingType(field.FieldType));
switch (typeCode)
{ {
case TypeCode.Boolean: case TypeCode.Boolean:
return "BOOLEAN"; return "BOOLEAN";
@ -125,7 +129,7 @@ namespace MontoyaTech.MySqlPlus
return "TINYINT"; return "TINYINT";
default: default:
throw new NotSupportedException($"Unsupported column type code: {code}"); throw new NotSupportedException($"Unsupported column type code: {typeCode}");
} }
} }
@ -168,58 +172,97 @@ namespace MontoyaTech.MySqlPlus
//Get our field type code //Get our field type code
var typeCode = Type.GetTypeCode(field.FieldType); var typeCode = Type.GetTypeCode(field.FieldType);
//If this field is a nullable, get the underlying type.
bool nullable = false;
if (field.FieldType.IsNullable())
{
typeCode = Type.GetTypeCode(Nullable.GetUnderlyingType(field.FieldType));
nullable = true;
}
//Read the value based on the type code. //Read the value based on the type code.
switch (typeCode) switch (typeCode)
{ {
case TypeCode.Boolean: case TypeCode.Boolean:
field.SetValue(row, reader.IsDBNull(columnIndex) ? default(bool) : reader.GetValue(columnIndex).ConvertToType<bool>()); field.SetValue(row, reader.IsDBNull(columnIndex) ? (nullable ? null : default(bool)) : reader.GetValue(columnIndex).ConvertToType<bool>());
break; break;
case TypeCode.Byte: case TypeCode.Byte:
field.SetValue(row, reader.IsDBNull(columnIndex) ? default(byte) : reader.GetValue(columnIndex).ConvertToType<byte>()); field.SetValue(row, reader.IsDBNull(columnIndex) ? (nullable ? null : default(byte)) : reader.GetValue(columnIndex).ConvertToType<byte>());
break; break;
case TypeCode.Char: case TypeCode.Char:
field.SetValue(row, reader.IsDBNull(columnIndex) ? default(char) : reader.GetValue(columnIndex).ConvertToType<char>()); field.SetValue(row, reader.IsDBNull(columnIndex) ? (nullable ? null : default(char)) : reader.GetValue(columnIndex).ConvertToType<char>());
break; break;
case TypeCode.Decimal: case TypeCode.Decimal:
field.SetValue(row, reader.IsDBNull(columnIndex) ? default(decimal) : reader.GetValue(columnIndex).ConvertToType<decimal>()); field.SetValue(row, reader.IsDBNull(columnIndex) ? (nullable ? null : default(decimal)) : reader.GetValue(columnIndex).ConvertToType<decimal>());
break; break;
case TypeCode.DateTime: case TypeCode.DateTime:
field.SetValue(row, reader.IsDBNull(columnIndex) ? default(DateTime) : reader.GetValue(columnIndex).ConvertToType<DateTime>()); field.SetValue(row, reader.IsDBNull(columnIndex) ? (nullable ? null : default(DateTime)) : reader.GetValue(columnIndex).ConvertToType<DateTime>());
break; break;
case TypeCode.Double: case TypeCode.Double:
field.SetValue(row, reader.IsDBNull(columnIndex) ? default(double) : reader.GetValue(columnIndex).ConvertToType<double>()); field.SetValue(row, reader.IsDBNull(columnIndex) ? (nullable ? null : default(double)) : reader.GetValue(columnIndex).ConvertToType<double>());
break; break;
case TypeCode.Int16: case TypeCode.Int16:
field.SetValue(row, reader.IsDBNull(columnIndex) ? default(short) : reader.GetValue(columnIndex).ConvertToType<short>()); field.SetValue(row, reader.IsDBNull(columnIndex) ? (nullable ? null : default(short)) : reader.GetValue(columnIndex).ConvertToType<short>());
break; break;
case TypeCode.Int32: case TypeCode.Int32:
field.SetValue(row, reader.IsDBNull(columnIndex) ? default(int) : reader.GetValue(columnIndex).ConvertToType<int>()); field.SetValue(row, reader.IsDBNull(columnIndex) ? (nullable ? null : default(int)) : reader.GetValue(columnIndex).ConvertToType<int>());
break; break;
case TypeCode.Int64: case TypeCode.Int64:
field.SetValue(row, reader.IsDBNull(columnIndex) ? default(long) : reader.GetValue(columnIndex).ConvertToType<long>()); field.SetValue(row, reader.IsDBNull(columnIndex) ? (nullable ? null : default(long)) : reader.GetValue(columnIndex).ConvertToType<long>());
break; break;
case TypeCode.SByte: case TypeCode.SByte:
field.SetValue(row, reader.IsDBNull(columnIndex) ? default(sbyte) : reader.GetValue(columnIndex).ConvertToType<sbyte>()); field.SetValue(row, reader.IsDBNull(columnIndex) ? (nullable ? null : default(sbyte)) : reader.GetValue(columnIndex).ConvertToType<sbyte>());
break; break;
case TypeCode.Single: case TypeCode.Single:
field.SetValue(row, reader.IsDBNull(columnIndex) ? default(float) : reader.GetValue(columnIndex).ConvertToType<float>()); field.SetValue(row, reader.IsDBNull(columnIndex) ? (nullable ? null : default(float)) : reader.GetValue(columnIndex).ConvertToType<float>());
break; break;
case TypeCode.String: case TypeCode.String:
field.SetValue(row, reader.IsDBNull(columnIndex) ? default(string) : reader.GetValue(columnIndex).ConvertToType<string>()); field.SetValue(row, reader.IsDBNull(columnIndex) ? default(string) : reader.GetValue(columnIndex).ConvertToType<string>());
break; break;
case TypeCode.UInt16: case TypeCode.UInt16:
field.SetValue(row, reader.IsDBNull(columnIndex) ? default(ushort) : reader.GetValue(columnIndex).ConvertToType<ushort>()); field.SetValue(row, reader.IsDBNull(columnIndex) ? (nullable ? null : default(ushort)) : reader.GetValue(columnIndex).ConvertToType<ushort>());
break; break;
case TypeCode.UInt32: case TypeCode.UInt32:
field.SetValue(row, reader.IsDBNull(columnIndex) ? default(uint) : reader.GetValue(columnIndex).ConvertToType<uint>()); field.SetValue(row, reader.IsDBNull(columnIndex) ? (nullable ? null: default(uint)) : reader.GetValue(columnIndex).ConvertToType<uint>());
break; break;
case TypeCode.UInt64: case TypeCode.UInt64:
field.SetValue(row, reader.IsDBNull(columnIndex) ? default(ulong) : reader.GetValue(columnIndex).ConvertToType<ulong>()); field.SetValue(row, reader.IsDBNull(columnIndex) ? (nullable ? null : default(ulong)) : reader.GetValue(columnIndex).ConvertToType<ulong>());
break; break;
default: default:
throw new NotSupportedException("Unsupported TypeCode"); throw new NotSupportedException("Unsupported TypeCode");
} }
} }
} }
/// <summary>
/// Returns whether or not a MySqlColumn can be nullable or not based on the field definition and a row.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="column"></param>
/// <param name="field"></param>
/// <param name="row"></param>
/// <returns></returns>
public static bool IsNullable<T>(this MySqlColumn column, FieldInfo field, T row)
{
var fieldType = field.FieldType;
var defaultValue = field.GetValue(row);
if (column.DefaultValue != null)
defaultValue = column.DefaultValue;
if (column.Converter != null)
fieldType = column.Converter.CreateInstance<MySqlColumnConverter>().ConvertTo(defaultValue).GetType();
if (fieldType.IsNullable())
return true;
if (fieldType.IsValueType)
return false;
return true;
}
} }
} }

View File

@ -321,11 +321,14 @@ namespace MontoyaTech.MySqlPlus
//Write the column data type //Write the column data type
builder.Append($"{column.GetMySqlColumnType(fields[i])} "); builder.Append($"{column.GetMySqlColumnType(fields[i])} ");
//Determine if this column is nullable
bool nullable = column.IsNullable(field, row);
//Write the column null information //Write the column null information
builder.Append($"{(column.Nullable ? "NULL" : "NOT NULL")} "); builder.Append($"{(nullable ? "NULL" : "NOT NULL")} ");
//Write the column default value if needed. (We can't do this if the column is auto increment) //Write the column default value if needed. (We can't do this if the column is auto increment)
if (column.Default && !column.AutoIncrement) if (!column.AutoIncrement)
{ {
var defaultValue = column.DefaultValue; var defaultValue = column.DefaultValue;
@ -333,13 +336,14 @@ namespace MontoyaTech.MySqlPlus
if (defaultValue == null) if (defaultValue == null)
defaultValue = field.GetValue(row); defaultValue = field.GetValue(row);
//Quirk, don't do this if the converter is null, and the default is null, and we are nullable. //If we have a converter, run the converter to get the true default value.
if (!(column.Converter == null && defaultValue == null && column.Nullable)) if (column.Converter != null)
{ defaultValue = column.Converter.CreateInstance<MySqlColumnConverter>().ConvertTo(defaultValue);
if (column.Converter != null)
defaultValue = column.Converter.CreateInstance<MySqlColumnConverter>().ConvertTo(defaultValue);
builder.Append($"{(column.Default ? $"DEFAULT @{i}" : "")} "); //If we have a default value, set it on the column.
if (defaultValue != null)
{
builder.Append($"DEFAULT @{i} ");
command.Parameters.AddWithValue($"@{i}", defaultValue); command.Parameters.AddWithValue($"@{i}", defaultValue);
} }

View File

@ -7,7 +7,7 @@
<AssemblyName>MontoyaTech.MySqlPlus</AssemblyName> <AssemblyName>MontoyaTech.MySqlPlus</AssemblyName>
<RootNamespace>MontoyaTech.MySqlPlus</RootNamespace> <RootNamespace>MontoyaTech.MySqlPlus</RootNamespace>
<Title>MontoyaTech.MySqlPlus</Title> <Title>MontoyaTech.MySqlPlus</Title>
<Version>1.0.9</Version> <Version>1.1.0</Version>
<Company>MontoyaTech</Company> <Company>MontoyaTech</Company>
<Description>A simple C# library to help work with MySql.</Description> <Description>A simple C# library to help work with MySql.</Description>
<Copyright>MontoyaTech 2023</Copyright> <Copyright>MontoyaTech 2023</Copyright>

View File

@ -635,5 +635,15 @@ namespace MontoyaTech.MySqlPlus
} }
} }
} }
/// <summary>
/// Returns whether or not a given type is a System Nullabe type.
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public static bool IsNullable(this Type type)
{
return type.IsGenericType && type.GetGenericTypeDefinition().IsEquivalentTo(typeof(Nullable<>));
}
} }
} }