aboutsummaryrefslogtreecommitdiff
path: root/docker
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2022-12-13 16:44:25 +0800
committercrupest <crupest@outlook.com>2022-12-20 20:32:53 +0800
commit90aca5d4ca4aabdf7b1bfcbca1ddf1305bd2afab (patch)
treeb646eaa164b4b2fc5f712ceddbb92b2b67865295 /docker
parent72f0786810ec3afc7a7e42fdeb392717eeb1055b (diff)
downloadcrupest-90aca5d4ca4aabdf7b1bfcbca1ddf1305bd2afab.tar.gz
crupest-90aca5d4ca4aabdf7b1bfcbca1ddf1305bd2afab.tar.bz2
crupest-90aca5d4ca4aabdf7b1bfcbca1ddf1305bd2afab.zip
Develop secret api. v36
Diffstat (limited to 'docker')
-rw-r--r--docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnInfo.cs125
-rw-r--r--docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/README.md42
-rw-r--r--docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/TableInfo.cs79
3 files changed, 52 insertions, 194 deletions
diff --git a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnInfo.cs b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnInfo.cs
index 0ac6e7b..e91c777 100644
--- a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnInfo.cs
+++ b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnInfo.cs
@@ -4,62 +4,6 @@ using System.Text;
namespace CrupestApi.Commons.Crud;
-public class ColumnHooks
-{
- // value:
- // null => not specified
- // DbNullValue => specified as NULL
- // other => specified as value
- public delegate void ColumnHookAction(ColumnInfo column, ref object? value);
-
- public ColumnHooks(ColumnHookAction afterSelect, ColumnHookAction beforeInsert, ColumnHookAction beforeUpdate)
- {
- AfterSelect = afterSelect;
- BeforeInsert = beforeInsert;
- BeforeUpdate = beforeUpdate;
- }
-
- /// <summary>Called after SELECT. Please use multicast if you want to customize it because there are many default behavior in it.</summary>
- /// <remarks>
- /// Called after column type transformation.
- /// value(in):
- /// null => not found in SELECT result
- /// DbNullValue => database NULL
- /// others => database value
- /// value(out):
- /// null/DbNullValue => return null
- /// others => return as is
- /// </remarks>
- public ColumnHookAction AfterSelect;
-
- /// <summary>Called before INSERT. Please use multicast if you want to customize it because there are many default behavior in it.</summary>
- /// <remarks>
- /// Called before column type transformation.
- /// value(in):
- /// null => not specified by insert clause
- /// DbNullValue => specified as database NULL
- /// other => specified as other value
- /// value(out):
- /// null/DbNullValue => save database NULL
- /// other => save the value as is
- /// </remarks>
- public ColumnHookAction BeforeInsert;
-
- /// <summary>Called before UPDATE. Please use multicast if you want to customize it because there are many default behavior in it.</summary
- /// <remarks>
- /// Called before column type transformation.
- /// value(in):
- /// null => not specified by update clause
- /// DbNullValue => specified as database NULL
- /// other => specified as other value
- /// value(out):
- /// null => not update
- /// DbNullValue => update to database NULL
- /// other => update to the value
- /// </remarks>
- public ColumnHookAction BeforeUpdate;
-}
-
public class ColumnInfo
{
private readonly AggregateColumnMetadata _metadata = new AggregateColumnMetadata();
@@ -72,12 +16,6 @@ public class ColumnInfo
Table = table;
_metadata.Add(metadata);
ColumnType = typeProvider.Get(clrType);
-
- Hooks = new ColumnHooks(
- new ColumnHooks.ColumnHookAction(OnAfterSelect),
- new ColumnHooks.ColumnHookAction(OnBeforeInsert),
- new ColumnHooks.ColumnHookAction(OnBeforeUpdate)
- );
}
/// <summary>
@@ -94,16 +32,12 @@ public class ColumnInfo
{
_metadata.Add(columnAttribute);
}
-
- Hooks = new ColumnHooks(
- new ColumnHooks.ColumnHookAction(OnAfterSelect),
- new ColumnHooks.ColumnHookAction(OnBeforeInsert),
- new ColumnHooks.ColumnHookAction(OnBeforeUpdate)
- );
}
public TableInfo Table { get; }
+ public Type EntityType => Table.EntityType;
+
// If null, there is no corresponding property.
public PropertyInfo? PropertyInfo { get; } = null;
@@ -111,8 +45,6 @@ public class ColumnInfo
public IColumnTypeInfo ColumnType { get; }
- public ColumnHooks Hooks { get; }
-
public bool IsPrimaryKey => Metadata.GetValueOrDefault(ColumnMetadataKeys.IsPrimaryKey) is true;
public bool IsAutoIncrement => Metadata.GetValueOrDefault(ColumnMetadataKeys.IsAutoIncrement) is true;
public bool IsNotNull => IsPrimaryKey || Metadata.GetValueOrDefault(ColumnMetadataKeys.NotNull) is true;
@@ -163,35 +95,31 @@ public class ColumnInfo
}
}
- public MethodInfo ValidatorMethod
+ public MethodInfo? ValidatorMethod
{
get
{
- object? value = Metadata.GetValueOrDefault(ColumnMetadataKeys.Validator);
+ object? value = Metadata.GetValueOrDefault(ColumnMetadataKeys.DefaultValueGenerator);
Debug.Assert(value is null || value is string);
+ MethodInfo? result;
if (value is null)
{
- return GetType().GetMethod(nameof(DefaultValidator))!;
+ string methodName = ColumnName + "Validator";
+ result = Table.EntityType.GetMethod(methodName, BindingFlags.Static);
}
else
{
string methodName = (string)value;
- return Table.EntityType.GetMethod(methodName, BindingFlags.Static) ?? throw new Exception("The validator does not exist.");
+ result = Table.EntityType.GetMethod(methodName, BindingFlags.Static) ?? throw new Exception("The validator does not exist.");
}
+
+ return result;
}
}
public void InvokeValidator(object value)
{
- ValidatorMethod.Invoke(null, new object?[] { this, value });
- }
-
- public static void DefaultValidator(ColumnInfo column, object value)
- {
- if (column.IsNotNull && value is DbNullValue)
- {
- throw new Exception("The column can't be null.");
- }
+ ValidatorMethod?.Invoke(null, new object?[] { this, value });
}
public object? InvokeDefaultValueGenerator()
@@ -199,37 +127,6 @@ public class ColumnInfo
return DefaultValueGeneratorMethod?.Invoke(null, new object?[] { this });
}
- public static object? DefaultDefaultValueGenerator(ColumnInfo column)
- {
- return DbNullValue.Instance;
- }
-
- private void TryCoerceStringFromNullToEmpty(ref object? value)
- {
- if (ColumnType.ClrType == typeof(string) && (Metadata.GetValueOrDefault<bool?>(ColumnMetadataKeys.DefaultEmptyForString) is true) && value is DbNullValue)
- {
- value = "";
- }
- }
-
- protected void OnAfterSelect(ColumnInfo column, ref object? value)
- {
- TryCoerceStringFromNullToEmpty(ref value);
- }
-
- protected void OnBeforeInsert(ColumnInfo column, ref object? value)
- {
- TryCoerceStringFromNullToEmpty(ref value);
- }
-
- protected void OnBeforeUpdate(ColumnInfo column, ref object? value)
- {
- if (IsNoUpdate && value is not null)
- throw new Exception("The column can't be updated.");
-
- TryCoerceStringFromNullToEmpty(ref value);
- }
-
public string GenerateCreateTableColumnString(string? dbProviderId = null)
{
StringBuilder result = new StringBuilder();
diff --git a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/README.md b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/README.md
index 22289cb..ca8a6f1 100644
--- a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/README.md
+++ b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/README.md
@@ -9,34 +9,34 @@ The ultimate CRUD scaffold finally comes.
### Select
1. Create select `what`, where clause, order clause, `Offset` and `Limit`.
-2. Check clauses' related columns are valid. Then generate sql string and param list.
-3. Convert param list to `Dapper` dynamic params with proper type conversion in `IColumnTypeInfo`. Execute sql and get `dynamic`s.
-4. For each column:
- 1. If column not in query result is null, null will be used to call hooks.
- 2. If column is `NULL`, `DbNullValue` will be used to call hooks.
- 3. Otherwise run conversion in `IColumnTypeInfo`.
- 4. Run hook `AfterSelect` for every column.
-5. Convert `dynamic`s to `TEntity`s.
+2. Check clauses' related columns are valid.
+3. Generate sql string and param list.
+4. Convert param list to `Dapper` dynamic params with proper type conversion in `IColumnTypeInfo`.
+5. Execute sql and get `dynamic`s.
+6. (Optional) Convert `dynamic`s to `TEntity`s.
### Insert
-1. Create insert clause consisting of insert items.
-2. Check clauses' related columns are valid. Then generate sql string and param list.
+1. Create insert clause.
+2. Check clauses' related columns are valid.
3. For each column:
- 1. If insert item exits and value is not null but the column `IsGenerated` is true, throw exception.
- 2. If insert item does not exist or value is `null` for that column, use default value generator to generate value. However, `DbNullValue` always means use `NULL` for that column.
+ 1. If insert item exists and value is not null but the column `IsGenerated` is true, throw exception.
+ 2. If insert item does not exist or value is `null`, use default value generator to generate value. However, `DbNullValue` always means use `NULL` for that column.
3. Coerce null to `DbNullValue`.
- 4. Run hook `BeforeInsert`.
- 5. Coerce null to `DbNullValue`.
- 6. Run validator.
-4. Convert param list to `Dapper` dynamic params with proper type conversion in `IColumnTypeInfo`. Execute sql and return `KeyColumn` value.
+ 4. Run validator to validate the value.
+ 5. If value is `DbNullValue`, `IsNotNull` is true and `IsAutoIncrement` is false, throw exception.
+4. Generate sql string and param list.
+5. Convert param list to `Dapper` dynamic params with proper type conversion in `IColumnTypeInfo`.
+6. Execute sql and return `KeyColumn` value.
### Update
-1. Create update clause consisted of update items, where clause.
+1. Create update clause, where clause.
2. Check clauses' related columns are valid. Then generate sql string and param list.
3. For each column:
- 1. If insert item does not exist, `null` will be used to call hooks. However, `DbNullValue` always means use `NULL` for that column.
- 2. Run hook `BeforeInsert`. If value is null, it means do not update this column.
- 3. Run validator if `value` is not null.
-4. Convert param list to `Dapper` dynamic params with proper type conversion in `IColumnTypeInfo`. Execute sql and get count of affected rows.
+ 1. If update item exists and value is not null but the column `IsNoUpdate` is true, throw exception.
+ 2. Invoke validator to validate the value.
+ 3. If `IsNotNull` is true and value is `DbNullValue`, throw exception.
+4. Generate sql string and param list.
+5. Convert param list to `Dapper` dynamic params with proper type conversion in `IColumnTypeInfo`.
+6. Execute sql and return count of affected rows.
diff --git a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/TableInfo.cs b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/TableInfo.cs
index 15b6320..869e987 100644
--- a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/TableInfo.cs
+++ b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/TableInfo.cs
@@ -417,38 +417,7 @@ CREATE TABLE {tableName}(
{
var (sql, parameters) = GenerateSelectSql(what, where, orderBy, skip, limit);
var queryResult = dbConnection.Query<dynamic>(sql, ConvertParameters(parameters));
- return queryResult.Select(d =>
- {
- Type dynamicType = d.GetType();
- foreach (var column in Columns)
- {
- object? value = null;
- var dynamicProperty = dynamicType.GetProperty(column.ColumnName);
- if (dynamicProperty is null)
- {
- column.Hooks.AfterSelect(column, ref value);
- }
- else
- {
- value = dynamicProperty.GetValue(d);
- if (value is null)
- value = DbNullValue.Instance;
- else
- value = column.ColumnType.ConvertFromDatabase(value);
- column.Hooks.AfterSelect(column, ref value);
- }
-
- if (dynamicProperty is not null)
- {
- if (value is null || value is DbNullValue)
- dynamicProperty.SetValue(d, null);
- else
- dynamicProperty.SetValue(d, value);
- }
- }
-
- return d;
- }).ToList();
+ return queryResult.ToList();
}
public virtual int SelectCount(IDbConnection dbConnection, IWhereClause? where = null, IOrderByClause? orderBy = null, int? skip = null, int? limit = null)
@@ -502,19 +471,12 @@ CREATE TABLE {tableName}(
foreach (var column in Columns)
{
InsertItem? item = insert.Items.SingleOrDefault(i => i.ColumnName == column.ColumnName);
- object? value;
- if (item is null || item.Value is null)
- {
- value = null;
- }
- else
- {
- value = item.Value;
- }
+
+ var value = item?.Value;
if (column.IsGenerated && value is not null)
{
- throw new Exception("The column is generated. You can't specify it explicitly.");
+ throw new Exception($"The column '{column.ColumnName}' is auto generated. You can't specify it explicitly.");
}
if (value is null)
@@ -527,17 +489,21 @@ CREATE TABLE {tableName}(
value = DbNullValue.Instance;
}
- column.Hooks.BeforeInsert(column, ref value);
-
- if (value is null)
- value = DbNullValue.Instance;
-
column.InvokeValidator(value);
if (value is DbNullValue)
+ {
+ if (column.IsNotNull && !column.IsAutoIncrement)
+ {
+ throw new Exception($"Column '{column.ColumnName}' is not nullable. Please specify a non-null value.");
+ }
+
realInsert.Add(column.ColumnName, null);
+ }
else
+ {
realInsert.Add(column.ColumnName, value);
+ }
if (item?.ColumnName == KeyColumn.ColumnName)
@@ -564,22 +530,17 @@ CREATE TABLE {tableName}(
foreach (var column in Columns)
{
UpdateItem? item = update.Items.FirstOrDefault(i => i.ColumnName == column.ColumnName);
-
- object? value;
- if (item is null)
- {
- value = null;
- }
- else
- {
- value = item.Value ?? DbNullValue.Instance;
- }
-
- column.Hooks.BeforeUpdate(column, ref value);
+ object? value = item?.Value;
if (value is not null)
{
+ if (column.IsNoUpdate)
+ {
+ throw new Exception($"The column '{column.ColumnName}' can't be update.");
+ }
+
column.InvokeValidator(value);
+
realUpdate.Add(column.ColumnName, value);
}
}