diff options
author | crupest <crupest@outlook.com> | 2022-12-10 15:07:12 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2022-12-20 20:32:53 +0800 |
commit | 8c478bb1a07a55b9056ada029e0d6f9fe34d8d38 (patch) | |
tree | e739a8e449a1fd021a3118d9ccfb277d3f02b062 /docker/crupest-api/CrupestApi | |
parent | ddce7fb5891d97eb66960687fe1fea4cb0bd7c94 (diff) | |
download | crupest-8c478bb1a07a55b9056ada029e0d6f9fe34d8d38.tar.gz crupest-8c478bb1a07a55b9056ada029e0d6f9fe34d8d38.tar.bz2 crupest-8c478bb1a07a55b9056ada029e0d6f9fe34d8d38.zip |
Develop secret api. v23
Diffstat (limited to 'docker/crupest-api/CrupestApi')
8 files changed, 100 insertions, 54 deletions
diff --git a/docker/crupest-api/CrupestApi/CrupestApi.Commons.Tests/Crud/ColumnTypeInfoTest.cs b/docker/crupest-api/CrupestApi/CrupestApi.Commons.Tests/Crud/ColumnTypeInfoTest.cs index 56ae06f..b9ec03e 100644 --- a/docker/crupest-api/CrupestApi/CrupestApi.Commons.Tests/Crud/ColumnTypeInfoTest.cs +++ b/docker/crupest-api/CrupestApi/CrupestApi.Commons.Tests/Crud/ColumnTypeInfoTest.cs @@ -23,4 +23,17 @@ public class ColumnTypeInfoTest Assert.Equal(value, typeInfo.ConvertFromDatabase(value)); Assert.Equal(value, typeInfo.ConvertToDatabase(value)); } + + [Fact] + public void DateTimeColumnTypeTest() + { + var dateTimeColumnTypeInfo = _provider.Get(typeof(DateTime)); + Assert.Equal(typeof(DateTime), dateTimeColumnTypeInfo.ClrType); + Assert.Equal(typeof(string), dateTimeColumnTypeInfo.DatabaseClrType); + + var dateTime = new DateTime(2000, 1, 1, 0, 0, 0, DateTimeKind.Utc); + var dateTimeString = "2000-01-01T00:00:00Z"; + Assert.Equal(dateTimeString, dateTimeColumnTypeInfo.ConvertToDatabase(dateTime)); + Assert.Equal(dateTime, dateTimeColumnTypeInfo.ConvertFromDatabase(dateTimeString)); + } } diff --git a/docker/crupest-api/CrupestApi/CrupestApi.Commons.Tests/Crud/SqlCompareHelper.cs b/docker/crupest-api/CrupestApi/CrupestApi.Commons.Tests/Crud/SqlCompareHelper.cs index c019e19..72b6218 100644 --- a/docker/crupest-api/CrupestApi/CrupestApi.Commons.Tests/Crud/SqlCompareHelper.cs +++ b/docker/crupest-api/CrupestApi/CrupestApi.Commons.Tests/Crud/SqlCompareHelper.cs @@ -4,6 +4,8 @@ namespace CrupestApi.Commons.Crud.Tests; public class SqlCompareHelper { + private static List<char> SymbolTokens = new List<char>() { '(', ')', ';' }; + public static List<string> SqlExtractWords(string? sql, bool toLower = true) { var result = new List<string>(); @@ -27,14 +29,14 @@ public class SqlCompareHelper wordBuilder = null; } } - else if (sql[current] == ';') + else if (SymbolTokens.Contains(sql[current])) { if (wordBuilder is not null) { result.Add(wordBuilder.ToString()); wordBuilder = null; } - result.Add(";"); + result.Add(sql[current].ToString()); } else { @@ -75,9 +77,9 @@ public class SqlCompareHelper [Fact] public void TestSqlExtractWords() { - var sql = "SELECT * FROM TableName WHERE id = @abcd;"; + var sql = "SELECT * FROM TableName WHERE (id = @abcd);"; var words = SqlExtractWords(sql); - Assert.Equal(new List<string> { "select", "*", "from", "tablename", "where", "id", "=", "@abcd", ";" }, words); + Assert.Equal(new List<string> { "select", "*", "from", "tablename", "where", "(", "id", "=", "@abcd", ")", ";" }, words); } } diff --git a/docker/crupest-api/CrupestApi/CrupestApi.Commons.Tests/Crud/TableInfoTest.cs b/docker/crupest-api/CrupestApi/CrupestApi.Commons.Tests/Crud/TableInfoTest.cs index d82c70f..c6791c6 100644 --- a/docker/crupest-api/CrupestApi/CrupestApi.Commons.Tests/Crud/TableInfoTest.cs +++ b/docker/crupest-api/CrupestApi/CrupestApi.Commons.Tests/Crud/TableInfoTest.cs @@ -1 +1,34 @@ +using Xunit.Abstractions; + namespace CrupestApi.Commons.Crud.Tests; + +public class TableInfoTest +{ + private static TableInfoFactory TableInfoFactory = new TableInfoFactory(new ColumnTypeProvider()); + + private TableInfo _tableInfo; + + public TableInfoTest() + { + _tableInfo = TableInfoFactory.Get(typeof(TestEntity)); + } + + [Fact] + public void TestColumnCount() + { + Assert.Equal(4, _tableInfo.ColumnInfos.Count); + Assert.Equal(3, _tableInfo.ColumnProperties.Count); + Assert.Equal(1, _tableInfo.NonColumnProperties.Count); + } + + [Fact] + public void GenerateSelectSqlTest() + { + var (sql, parameters) = _tableInfo.GenerateSelectSql(WhereClause.Create().Eq("Name", "Hello")); + var parameterName = parameters.ParameterNames.First(); + + // TODO: Is there a way to auto detect parameters? + SqlCompareHelper.SqlEqual($"SELECT * FROM TestEntity WHERE (Name = @{parameterName})", sql); + Assert.Equal("Hello", parameters.Get<string>(parameterName)); + } +} diff --git a/docker/crupest-api/CrupestApi/CrupestApi.Commons.Tests/Crud/TestEntity.cs b/docker/crupest-api/CrupestApi/CrupestApi.Commons.Tests/Crud/TestEntity.cs new file mode 100644 index 0000000..ca84d5a --- /dev/null +++ b/docker/crupest-api/CrupestApi/CrupestApi.Commons.Tests/Crud/TestEntity.cs @@ -0,0 +1,15 @@ +namespace CrupestApi.Commons.Crud.Tests; + +public class TestEntity +{ + [Column(NotNull = true)] + public string Name { get; set; } = default!; + + [Column(NotNull = true)] + public int Age { get; set; } + + [Column] + public float? Height { get; set; } + + public string NonColumn { get; set; } = "Not A Column"; +} diff --git a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnInfo.cs b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnInfo.cs index d278d23..88b5ced 100644 --- a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnInfo.cs +++ b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnInfo.cs @@ -45,6 +45,7 @@ public class ColumnInfo public ColumnInfo(TableInfo table, PropertyInfo propertyInfo, IColumnTypeProvider typeProvider) { Table = table; + PropertyInfo = propertyInfo; ColumnType = typeProvider.Get(propertyInfo.PropertyType); var columnAttribute = propertyInfo.GetCustomAttribute<ColumnAttribute>(); @@ -103,7 +104,7 @@ public class ColumnInfo { object? value = Metadata.GetValueOrDefault(ColumnMetadataKeys.ColumnName); Debug.Assert(value is null || value is string); - return (string?)value ?? PropertyInfo?.Name ?? throw new Exception("Failed to get column name."); + return ((string?)value ?? PropertyInfo?.Name) ?? throw new Exception("Failed to get column name."); } } diff --git a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnTypeInfo.cs b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnTypeInfo.cs index 7591271..c678e0e 100644 --- a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnTypeInfo.cs +++ b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnTypeInfo.cs @@ -77,11 +77,6 @@ public interface IColumnTypeInfo }; } - JsonConverter? JsonConverter - { - get { return null; } - } - // You must override this method if ClrType != DatabaseClrType object? ConvertFromDatabase(object? databaseValue) { @@ -110,47 +105,28 @@ public class SimpleColumnTypeInfo<T> : IColumnTypeInfo public class DateTimeColumnTypeInfo : IColumnTypeInfo { - private DateTimeJsonConverter _jsonConverter = new DateTimeJsonConverter(); - public Type ClrType => typeof(DateTime); public Type DatabaseClrType => typeof(string); - public JsonConverter JsonConverter => _jsonConverter; - public object? ConvertToDatabase(object? value) { if (value is null) return null; Debug.Assert(value is DateTime); - return ((DateTime)value).ToUniversalTime().ToString("sZ"); + return ((DateTime)value).ToUniversalTime().ToString("s") + "Z"; } public object? ConvertFromDatabase(object? databaseValue) { if (databaseValue is null) return null; Debug.Assert(databaseValue is string); - return DateTime.ParseExact((string)databaseValue, "sZ", null, DateTimeStyles.AssumeUniversal); - } -} - -public class DateTimeJsonConverter : JsonConverter<DateTime> -{ - public override bool HandleNull => false; - - public override bool CanConvert(Type typeToConvert) - { - return typeToConvert == typeof(DateTime); - } - - public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - var s = reader.GetString(); - if (s is null) throw new Exception("Can't convert null to DateTime."); - return DateTime.ParseExact(s, "uZ", null, DateTimeStyles.AssumeUniversal); - } - - public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options) - { - writer.WriteStringValue(value.ToUniversalTime().ToString("uZ")); + var databaseString = (string)databaseValue; + var dateTimeStyles = DateTimeStyles.None; + if (databaseString.Length > 0 && databaseString[^1] == 'Z') + { + databaseString = databaseString.Substring(0, databaseString.Length - 1); + dateTimeStyles = DateTimeStyles.AssumeUniversal & DateTimeStyles.AdjustToUniversal; + } + return DateTime.ParseExact(databaseString, "s", null, dateTimeStyles); } } @@ -171,6 +147,7 @@ public class ColumnTypeProvider : IColumnTypeProvider _typeMap.Add(IColumnTypeInfo.DateTimeColumnTypeInfo.ClrType, IColumnTypeInfo.DateTimeColumnTypeInfo); } + // This is thread-safe. public IColumnTypeInfo Get(Type clrType) { if (_typeMap.TryGetValue(clrType, out var typeInfo)) @@ -179,7 +156,7 @@ public class ColumnTypeProvider : IColumnTypeProvider } else { - if (clrType == typeof(Nullable<>)) + if (clrType.IsGenericType && clrType.GetGenericTypeDefinition() == typeof(Nullable<>)) { clrType = clrType.GetGenericArguments()[0]; return Get(clrType); diff --git a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/TableInfo.cs b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/TableInfo.cs index 9977465..28dc1ad 100644 --- a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/TableInfo.cs +++ b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/TableInfo.cs @@ -35,7 +35,7 @@ public class TableInfo foreach (var property in properties) { - if (PropertyIsColumn(property)) + if (CheckPropertyIsColumn(property)) { var columnInfo = new ColumnInfo(this, property, _columnTypeProvider); columnInfos.Add(columnInfo); @@ -89,7 +89,7 @@ public class TableInfo public IReadOnlyList<PropertyInfo> NonColumnProperties { get; } public IReadOnlyList<string> ColumnNameList => _lazyColumnNameList.Value; - protected bool PropertyIsColumn(PropertyInfo property) + protected bool CheckPropertyIsColumn(PropertyInfo property) { var columnAttribute = property.GetCustomAttribute<ColumnAttribute>(); if (columnAttribute is null) return false; @@ -469,17 +469,21 @@ public class TableInfoFactory : ITableInfoFactory _columnTypeProvider = columnTypeProvider; } + // This is thread-safe. public TableInfo Get(Type type) { - if (_cache.TryGetValue(type, out var tableInfo)) + lock (_cache) { - return tableInfo; - } - else - { - tableInfo = new TableInfo(type, _columnTypeProvider); - _cache.Add(type, tableInfo); - return tableInfo; + if (_cache.TryGetValue(type, out var tableInfo)) + { + return tableInfo; + } + else + { + tableInfo = new TableInfo(type, _columnTypeProvider); + _cache.Add(type, tableInfo); + return tableInfo; + } } } } diff --git a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/WhereClause.cs b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/WhereClause.cs index 8ae2c01..98fe49d 100644 --- a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/WhereClause.cs +++ b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/WhereClause.cs @@ -22,6 +22,12 @@ public class CompositeWhereClause : IWhereClause public bool ParenthesesSubclause { get; } public List<IWhereClause> Subclauses { get; } + public CompositeWhereClause Eq(string column, object? value) + { + Subclauses.Add(SimpleCompareWhereClause.Eq(column, value)); + return this; + } + public (string sql, DynamicParameters parameters) GenerateSql(string? dbProviderId = null) { var parameters = new DynamicParameters(); @@ -174,9 +180,4 @@ public class WhereClause : AndWhereClause { Subclauses.Add(subclause); } - - public void Eq(string column, object? value) - { - Subclauses.Add(SimpleCompareWhereClause.Eq(column, value)); - } } |