aboutsummaryrefslogtreecommitdiff
path: root/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2022-12-10 20:24:59 +0800
committercrupest <crupest@outlook.com>2022-12-20 20:32:53 +0800
commitc53adadcbf93a3b5c1f9c8e2b88bdd0efb122709 (patch)
treecd901fb537367c3340d47ccd537c4ae06b9af337 /docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud
parentf208e75f9e074a3faab489de1093f660b87c2ec7 (diff)
downloadcrupest-c53adadcbf93a3b5c1f9c8e2b88bdd0efb122709.tar.gz
crupest-c53adadcbf93a3b5c1f9c8e2b88bdd0efb122709.tar.bz2
crupest-c53adadcbf93a3b5c1f9c8e2b88bdd0efb122709.zip
Develop secret api. v25
Diffstat (limited to 'docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud')
-rw-r--r--docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnInfo.cs6
-rw-r--r--docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnMetadata.cs10
-rw-r--r--docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/CrudService.cs31
-rw-r--r--docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/CrudWebApplicationExtensions.cs12
-rw-r--r--docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/EntityJsonHelper.cs36
-rw-r--r--docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/TableInfo.cs55
6 files changed, 136 insertions, 14 deletions
diff --git a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnInfo.cs b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnInfo.cs
index f1fb99b..545397d 100644
--- a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnInfo.cs
+++ b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnInfo.cs
@@ -158,6 +158,12 @@ public class ColumnInfo
public bool IsNotNull => IsPrimaryKey || Metadata.GetValueOrDefault(ColumnMetadataKeys.NotNull) is true;
public bool IsClientGenerate => Metadata.GetValueOrDefault(ColumnMetadataKeys.ClientGenerate) is true;
public bool IsNoUpdate => Metadata.GetValueOrDefault(ColumnMetadataKeys.NoUpdate) is true;
+ /// <summary>
+ /// This only returns metadata value. It doesn't not fall back to primary column. If you want to get the real key column, go to table info.
+ /// </summary>
+ /// <seealso cref="ColumnMetadataKeys.ActAsKey"/>
+ /// <seealso cref="TableInfo.KeyColumn"/>
+ public bool IsSpecifiedAsKey => Metadata.GetValueOrDefault(ColumnMetadataKeys.ActAsKey) is true;
public ColumnIndexType Index => Metadata.GetValueOrDefault<ColumnIndexType?>(ColumnMetadataKeys.Index) ?? ColumnIndexType.None;
diff --git a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnMetadata.cs b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnMetadata.cs
index 1ca2ce8..9fb3999 100644
--- a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnMetadata.cs
+++ b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnMetadata.cs
@@ -29,6 +29,11 @@ public static class ColumnMetadataKeys
/// </summary>
/// <returns></returns>
public const string NoUpdate = nameof(ColumnAttribute.NoUpdate);
+
+ /// <summary>
+ /// This column acts as key when get one entity for http get method in path.
+ /// </summary>
+ public const string ActAsKey = nameof(ColumnAttribute.ActAsKey);
}
public interface IColumnMetadata
@@ -105,6 +110,11 @@ public class ColumnAttribute : Attribute, IColumnMetadata
/// <see cref="ColumnMetadataKeys.NoUpdate"/>
public bool NoUpdate { get; init; }
+ /// <see cref="ColumnMetadataKeys.ActAsKey"/>
+ public bool ActAsKey { get; init; }
+
+
+
public bool TryGetValue(string key, out object? value)
{
var property = GetType().GetProperty(key);
diff --git a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/CrudService.cs b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/CrudService.cs
index 811b2e6..af6a8d5 100644
--- a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/CrudService.cs
+++ b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/CrudService.cs
@@ -1,13 +1,16 @@
using System.Data;
+using System.Text.Json;
using Dapper;
namespace CrupestApi.Commons.Crud;
+// TODO: Register this.
public class CrudService<TEntity> : IDisposable where TEntity : class
{
protected readonly TableInfo _table;
protected readonly string? _connectionName;
protected readonly IDbConnection _dbConnection;
+ protected readonly EntityJsonHelper _jsonHelper;
private readonly ILogger<CrudService<TEntity>> _logger;
public CrudService(string? connectionName, ITableInfoFactory tableInfoFactory, IDbConnectionFactory dbConnectionFactory, ILoggerFactory loggerFactory)
@@ -15,6 +18,7 @@ public class CrudService<TEntity> : IDisposable where TEntity : class
_connectionName = connectionName;
_table = tableInfoFactory.Get(typeof(TEntity));
_dbConnection = dbConnectionFactory.Get(_connectionName);
+ _jsonHelper = new EntityJsonHelper(_table);
_logger = loggerFactory.CreateLogger<CrudService<TEntity>>();
if (!_table.CheckExistence(_dbConnection))
@@ -50,12 +54,14 @@ public class CrudService<TEntity> : IDisposable where TEntity : class
return _table.SelectCount(_dbConnection, filter);
}
- public int Insert(IInsertClause insertClause)
+ // Return the key.
+ public object Insert(IInsertClause insertClause)
{
return _table.Insert(_dbConnection, insertClause);
}
- public int Insert(TEntity entity)
+ // Return the key.
+ public object Insert(TEntity entity)
{
return _table.Insert(_dbConnection, _table.GenerateInsertClauseFromEntity(entity));
}
@@ -69,4 +75,25 @@ public class CrudService<TEntity> : IDisposable where TEntity : class
{
return _table.Delete(_dbConnection, filter);
}
+
+ public TEntity SelectByKey(object key)
+ {
+ return Select(WhereClause.Create().Eq(_table.KeyColumn.ColumnName, key)).Single();
+ }
+
+ public List<JsonDocument> SelectAsJson(IWhereClause? filter)
+ {
+ return Select(filter).Select(e => _jsonHelper.ConvertEntityToJson(e)).ToList();
+ }
+
+ public JsonDocument SelectAsJsonByKey(object key)
+ {
+ return SelectAsJson(WhereClause.Create().Eq(_table.KeyColumn.ColumnName, key)).Single();
+ }
+
+ public object InsertFromJson(JsonDocument? json)
+ {
+ // TODO: Implement this.
+ throw new NotImplementedException();
+ }
}
diff --git a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/CrudWebApplicationExtensions.cs b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/CrudWebApplicationExtensions.cs
index 3467625..46b2e5b 100644
--- a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/CrudWebApplicationExtensions.cs
+++ b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/CrudWebApplicationExtensions.cs
@@ -2,10 +2,20 @@ namespace CrupestApi.Commons.Crud;
public static class CrudWebApplicationExtensions
{
- public static WebApplication UseCrud(this WebApplication app, string path)
+ public static WebApplication UseCrud<TEntity>(this WebApplication app, string path) where TEntity : class
{
app.MapGet(path, async (context) =>
{
+ var crudService = context.RequestServices.GetRequiredService<CrudService<TEntity>>();
+
+ var result = crudService.SelectAsJson(null);
+
+ await context.ResponseJsonAsync(result);
+ });
+
+ app.MapPost(path, async (context) =>
+ {
+ var crudService = context.RequestServices.GetRequiredService<CrudService<TEntity>>();
});
diff --git a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/EntityJsonHelper.cs b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/EntityJsonHelper.cs
new file mode 100644
index 0000000..a1e4583
--- /dev/null
+++ b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/EntityJsonHelper.cs
@@ -0,0 +1,36 @@
+using System.Text.Json;
+
+namespace CrupestApi.Commons.Crud;
+
+public class EntityJsonHelper
+{
+ private readonly TableInfo _table;
+
+ public EntityJsonHelper(TableInfo table)
+ {
+ _table = table;
+ }
+
+ public virtual JsonDocument ConvertEntityToJson(object? entity)
+ {
+ if (entity is null) return JsonSerializer.SerializeToDocument<object?>(null);
+
+ var result = new Dictionary<string, object?>();
+
+ foreach (var column in _table.ColumnInfos)
+ {
+ if (column.PropertyInfo is not null)
+ {
+ result.Add(column.ColumnName, column.PropertyInfo.GetValue(entity));
+ }
+ }
+
+ return JsonSerializer.SerializeToDocument(result);
+ }
+
+ public virtual object? ConvertJsonToEntity(JsonDocument? json)
+ {
+ // TODO: Implement this.
+ throw new NotImplementedException();
+ }
+}
diff --git a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/TableInfo.cs b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/TableInfo.cs
index 5bb19ad..498529c 100644
--- a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/TableInfo.cs
+++ b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/TableInfo.cs
@@ -27,8 +27,9 @@ public class TableInfo
var columnInfos = new List<ColumnInfo>();
- bool hasPrimaryKey = false;
bool hasId = false;
+ ColumnInfo? primaryKeyColumn = null;
+ ColumnInfo? keyColumn = null;
List<PropertyInfo> columnProperties = new();
List<PropertyInfo> nonColumnProperties = new();
@@ -40,11 +41,21 @@ public class TableInfo
var columnInfo = new ColumnInfo(this, property, _columnTypeProvider);
columnInfos.Add(columnInfo);
if (columnInfo.IsPrimaryKey)
- hasPrimaryKey = true;
+ {
+ primaryKeyColumn = columnInfo;
+ }
if (columnInfo.ColumnName.Equals("id", StringComparison.OrdinalIgnoreCase))
{
hasId = true;
}
+ if (columnInfo.IsSpecifiedAsKey)
+ {
+ if (keyColumn is not null)
+ {
+ throw new Exception("Already exists a key column.");
+ }
+ keyColumn = columnInfo;
+ }
columnProperties.Add(property);
}
else
@@ -53,14 +64,21 @@ public class TableInfo
}
}
- if (!hasPrimaryKey)
+ if (primaryKeyColumn is null)
{
if (hasId) throw new Exception("A column named id already exists but is not primary key.");
- var columnInfo = CreateAutoIdColumn();
- columnInfos.Add(columnInfo);
+ primaryKeyColumn = CreateAutoIdColumn();
+ columnInfos.Add(primaryKeyColumn);
+ }
+
+ if (keyColumn is null)
+ {
+ keyColumn = primaryKeyColumn;
}
ColumnInfos = columnInfos;
+ PrimaryKeyColumn = primaryKeyColumn;
+ KeyColumn = keyColumn;
ColumnProperties = columnProperties;
NonColumnProperties = nonColumnProperties;
@@ -85,6 +103,12 @@ public class TableInfo
public Type EntityType { get; }
public string TableName { get; }
public IReadOnlyList<ColumnInfo> ColumnInfos { get; }
+ public ColumnInfo PrimaryKeyColumn { get; }
+ /// <summary>
+ /// Maybe not the primary key. But acts as primary key.
+ /// </summary>
+ /// <seealso cref="ColumnMetadataKeys.ActAsKey"/>
+ public ColumnInfo KeyColumn { get; }
public IReadOnlyList<PropertyInfo> ColumnProperties { get; }
public IReadOnlyList<PropertyInfo> NonColumnProperties { get; }
public IReadOnlyList<string> ColumnNameList => _lazyColumnNameList.Value;
@@ -412,10 +436,10 @@ CREATE TABLE {tableName}(
});
}
- public virtual int Insert(IDbConnection dbConnection, IInsertClause insert)
+ // Returns the insert entity's key.
+ public object Insert(IDbConnection dbConnection, IInsertClause insert)
{
- var (sql, parameters) = GenerateInsertSql(insert);
-
+ object? key = null;
foreach (var column in ColumnInfos)
{
InsertItem? item = insert.Items.FirstOrDefault(i => i.ColumnName == column.ColumnName);
@@ -423,16 +447,25 @@ CREATE TABLE {tableName}(
column.Hooks.BeforeInsert(column, ref value);
if (item is null)
{
- if (value is not null)
- insert.Items.Add(new InsertItem(column.ColumnName, value));
+ item = new InsertItem(column.ColumnName, value);
+ insert.Items.Add(item);
}
else
{
item.Value = value;
}
+
+ if (item.ColumnName == KeyColumn.ColumnName)
+ {
+ key = item.Value;
+ }
}
- return dbConnection.Execute(sql, ConvertParameters(parameters));
+ var (sql, parameters) = GenerateInsertSql(insert);
+
+ dbConnection.Execute(sql, ConvertParameters(parameters));
+
+ return key ?? throw new Exception("No key???");
}
public virtual int Update(IDbConnection dbConnection, IWhereClause? where, IUpdateClause update)