aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docker/crupest-api/CrupestApi/.gitignore1
-rw-r--r--docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnInfo.cs50
-rw-r--r--docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnTypeInfo.cs10
-rw-r--r--docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/CrudService.cs51
-rw-r--r--docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/TableInfo.cs44
5 files changed, 102 insertions, 54 deletions
diff --git a/docker/crupest-api/CrupestApi/.gitignore b/docker/crupest-api/CrupestApi/.gitignore
index f3d2489..371ea59 100644
--- a/docker/crupest-api/CrupestApi/.gitignore
+++ b/docker/crupest-api/CrupestApi/.gitignore
@@ -1,3 +1,4 @@
+.vs
obj
bin
dev-config.json
diff --git a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnInfo.cs b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnInfo.cs
index 8b4607d..b76e1ae 100644
--- a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnInfo.cs
+++ b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnInfo.cs
@@ -1,4 +1,5 @@
using System.Reflection;
+using System.Text;
namespace CrupestApi.Commons.Crud;
@@ -15,8 +16,13 @@ public class ColumnInfo
}
// A column with no property.
- public ColumnInfo(Type entityType, string sqlColumnName, bool isPrimaryKey, bool isAutoIncrement, IColumnTypeInfo typeInfo)
+ public ColumnInfo(Type entityType, string sqlColumnName, bool isPrimaryKey, bool isAutoIncrement, IColumnTypeInfo typeInfo, ColumnTypeInfoRegistry? typeRegistry = null)
{
+ if (typeRegistry is null)
+ {
+ typeRegistry = ColumnTypeInfoRegistry.Singleton;
+ }
+
EntityType = entityType;
PropertyName = null;
PropertyType = typeof(int);
@@ -26,10 +32,16 @@ public class ColumnInfo
Nullable = false;
IsPrimaryKey = isPrimaryKey;
IsAutoIncrement = isAutoIncrement;
+ TypeRegistry = typeRegistry;
}
- public ColumnInfo(Type entityType, string entityPropertyName)
+ public ColumnInfo(Type entityType, string entityPropertyName, ColumnTypeInfoRegistry? typeRegistry = null)
{
+ if (typeRegistry is null)
+ {
+ typeRegistry = ColumnTypeInfoRegistry.Singleton;
+ }
+
EntityType = entityType;
PropertyName = entityPropertyName;
@@ -52,8 +64,9 @@ public class ColumnInfo
SqlColumnName = columnAttribute.DatabaseName ?? PropertyName;
Nullable = !columnAttribute.NonNullable;
}
- ColumnTypeInfo = ColumnTypeInfoRegistry.Singleton.GetRequiredByDataType(PropertyRealType);
+ ColumnTypeInfo = typeRegistry.GetRequiredByDataType(PropertyRealType);
+ TypeRegistry = typeRegistry;
}
public Type EntityType { get; }
@@ -62,8 +75,37 @@ public class ColumnInfo
public Type PropertyType { get; }
public Type PropertyRealType { get; }
public string SqlColumnName { get; }
+ public ColumnTypeInfoRegistry TypeRegistry { get; set; }
public IColumnTypeInfo ColumnTypeInfo { get; }
public bool Nullable { get; }
public bool IsPrimaryKey { get; }
public bool IsAutoIncrement { get; }
-} \ No newline at end of file
+
+ public string SqlType => TypeRegistry.GetSqlType(ColumnTypeInfo);
+
+ public string GenerateCreateTableColumnString()
+ {
+ StringBuilder result = new StringBuilder();
+ result.Append(SqlColumnName);
+ result.Append(' ');
+ result.Append(SqlType);
+ if (IsPrimaryKey)
+ {
+ result.Append(' ');
+ result.Append("PRIMARY KEY");
+ }
+ else if (!Nullable)
+ {
+ result.Append(' ');
+ result.Append(" NOT NULL");
+ }
+
+ if (IsAutoIncrement)
+ {
+ result.Append(' ');
+ result.Append("AUTOINCREMENT");
+ }
+
+ return result.ToString();
+ }
+}
diff --git a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnTypeInfo.cs b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnTypeInfo.cs
index 1bdc9c0..ff8ccea 100644
--- a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnTypeInfo.cs
+++ b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnTypeInfo.cs
@@ -38,6 +38,7 @@ public interface IColumnTypeInfo
public interface IBuiltinColumnTypeInfo : IColumnTypeInfo
{
+ /// To use for non-builtin type, use <see cref="ColumnTypeInfoRegistry.GetSqlType(IColumnTypeInfo)" /> because we need registry to query more information.
string GetSqlType();
}
@@ -188,11 +189,11 @@ public class ColumnTypeInfoRegistry
return GetByDataType(type) ?? throw new Exception("Unsupported type.");
}
- public string GetSqlType(Type type)
+ public string GetSqlType(IColumnTypeInfo columnTypeInfo)
{
EnsureValidity();
- IColumnTypeInfo? current = GetByDataType(type);
+ IColumnTypeInfo? current = columnTypeInfo;
if (current is null)
{
throw new Exception("Unsupported type for sql.");
@@ -207,6 +208,11 @@ public class ColumnTypeInfoRegistry
return ((IBuiltinColumnTypeInfo)current).GetSqlType();
}
+ public string GetSqlType(Type type)
+ {
+ return GetSqlType(GetRequiredByDataType(type));
+ }
+
public void Validate()
{
foreach (var columnTypeInfo in _list)
diff --git a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/CrudService.cs b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/CrudService.cs
index bc4ed50..63a247b 100644
--- a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/CrudService.cs
+++ b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/CrudService.cs
@@ -7,20 +7,17 @@ namespace CrupestApi.Commons.Crud;
public class CrudService<TEntity>
{
+ protected readonly TableInfo _table;
protected readonly IOptionsSnapshot<CrupestApiConfig> _crupestApiOptions;
protected readonly ILogger<CrudService<TEntity>> _logger;
public CrudService(IOptionsSnapshot<CrupestApiConfig> crupestApiOptions, ILogger<CrudService<TEntity>> logger)
{
+ _table = new TableInfo(typeof(TEntity));
_crupestApiOptions = crupestApiOptions;
_logger = logger;
}
- public virtual string GetTableName()
- {
- return typeof(TEntity).Name;
- }
-
public virtual string GetDbConnectionString()
{
var fileName = Path.Combine(_crupestApiOptions.Value.DataDir, "crupest-api.db");
@@ -40,57 +37,17 @@ public class CrudService<TEntity>
return connection;
}
- public virtual async Task<bool> CheckDatabaseExist(SqliteConnection connection)
- {
- var tableName = GetTableName();
- var count = (await connection.QueryAsync<int>(
- @"SELECT count(*) FROM sqlite_schema WHERE type = 'table' AND tbl_name = @TableName;",
- new { TableName = tableName })).Single();
- if (count == 0)
- {
- return false;
- }
- else if (count > 1)
- {
- throw new DatabaseInternalException($"More than 1 table has name {tableName}. What happened?");
- }
- else
- {
- return true;
- }
- }
-
- public string GetSqlType(Type type)
- {
- return ColumnTypeInfoRegistry.Singleton.GetSqlType(type);
- }
-
- public string GetCreateTableColumnSql()
- {
- var properties = typeof(TEntity).GetProperties();
- var sql = string.Join(", ", properties.Select(p => $"{p.Name} {GetSqlType(p.PropertyType)}"));
- return sql;
- }
-
public virtual async Task DoInitializeDatabase(SqliteConnection connection)
{
await using var transaction = await connection.BeginTransactionAsync();
- var tableName = GetTableName();
- var columnSql = GetCreateTableColumnSql();
- var sql = $@"
-CREATE TABLE {tableName}(
- id INTEGER PRIMARY KEY AUTOINCREMENT,
- {columnSql}
-);
- ";
- await connection.ExecuteAsync(sql, transaction: transaction);
+ await connection.ExecuteAsync(_table.GenerateCreateTableSql(), transaction: transaction);
await transaction.CommitAsync();
}
public virtual async Task<SqliteConnection> EnsureDatabase()
{
var connection = await CreateDbConnection();
- var exist = await CheckDatabaseExist(connection);
+ var exist = await _table.CheckExistence(connection);
if (!exist)
{
await DoInitializeDatabase(connection);
diff --git a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/TableInfo.cs b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/TableInfo.cs
index fb9e1ad..660cd4d 100644
--- a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/TableInfo.cs
+++ b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/TableInfo.cs
@@ -1,9 +1,20 @@
+using Dapper;
+using Microsoft.Data.Sqlite;
+
namespace CrupestApi.Commons.Crud;
public class TableInfo
{
+ // For custom name.
public TableInfo(Type entityType)
+ : this(entityType.Name, entityType)
+ {
+
+ }
+
+ public TableInfo(string tableName, Type entityType)
{
+ TableName = tableName;
EntityType = entityType;
var properties = entityType.GetProperties();
@@ -38,6 +49,7 @@ public class TableInfo
}
public Type EntityType { get; }
+ public string TableName { get; }
public IReadOnlyList<ColumnInfo> ColumnInfos { get; }
public void CheckValidity()
@@ -68,6 +80,36 @@ public class TableInfo
public string GenerateCreateTableSql()
{
- throw new NotImplementedException();
+ var tableName = TableName;
+ var columnSql = string.Join(",\n", ColumnInfos.Select(c => c.GenerateCreateTableColumnString()));
+
+ var sql = $@"
+CREATE TABLE {tableName}(
+ {columnSql}
+);
+ ";
+
+ return sql;
+ }
+
+ public async Task<bool> CheckExistence(SqliteConnection connection)
+ {
+ var tableName = TableName;
+ var count = (await connection.QueryAsync<int>(
+ @"SELECT count(*) FROM sqlite_schema WHERE type = 'table' AND tbl_name = @TableName;",
+ new { TableName = tableName })).Single();
+ if (count == 0)
+ {
+ return false;
+ }
+ else if (count > 1)
+ {
+ throw new DatabaseInternalException($"More than 1 table has name {tableName}. What happened?");
+ }
+ else
+ {
+ return true;
+ }
+
}
} \ No newline at end of file