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 | 81b106a1bfc225abcee1c9b5cfad64489e8cb24b (patch) | |
| tree | e739a8e449a1fd021a3118d9ccfb277d3f02b062 /docker/crupest-api | |
| parent | 2c9e38fbb434759593825f3893563dcd0c3806bb (diff) | |
| download | crupest-81b106a1bfc225abcee1c9b5cfad64489e8cb24b.tar.gz crupest-81b106a1bfc225abcee1c9b5cfad64489e8cb24b.tar.bz2 crupest-81b106a1bfc225abcee1c9b5cfad64489e8cb24b.zip  | |
Develop secret api. v23
Diffstat (limited to 'docker/crupest-api')
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)); -    }  }  | 
