using System.Reflection; using System.Text; using Cassandra; using System.ComponentModel.DataAnnotations; using JiShe.CollectBus.Common.Attributes; using Volo.Abp.Data; namespace JiShe.CollectBus.Cassandra.Extensions { public static class SessionExtension { public static void CreateTable(this ISession session,string? defaultKeyspace=null) where TEntity : class { var type = typeof(TEntity); var tableAttribute = type.GetCustomAttribute(); var tableName = tableAttribute?.Name ?? type.Name.ToLower(); var tableKeyspace = session.Keyspace; var properties = type.GetProperties(); // 分区键设置 var primaryKey = properties.FirstOrDefault(p => p.GetCustomAttribute() != null); if (primaryKey == null) { throw new InvalidOperationException($"No primary key defined for type {type.Name}"); } // 集群键设置 var clusteringKeys = properties.Where(p => p.GetCustomAttribute() != null).Select(a=>a.Name).ToList(); var clusteringKeyCql = string.Empty; if (clusteringKeys.Any()) { clusteringKeyCql = $", {string.Join(", ", clusteringKeys)}"; } var cql = new StringBuilder(); cql.Append($"CREATE TABLE IF NOT EXISTS {tableKeyspace}.{tableName} ("); foreach (var prop in properties) { var ignoreAttribute = prop.GetCustomAttribute(); if (ignoreAttribute != null) continue; var columnName = prop.Name.ToLower(); var cqlType = GetCassandraType(prop.PropertyType); cql.Append($"{columnName} {cqlType}, "); } cql.Length -= 2; // Remove last comma and space cql.Append($", PRIMARY KEY (({primaryKey.Name.ToLower()}){clusteringKeyCql}))"); session.Execute(cql.ToString()); } private static string GetCassandraType(Type type) { // 基础类型处理 switch (Type.GetTypeCode(type)) { case TypeCode.String: return "text"; case TypeCode.Int32: return "int"; case TypeCode.Int64: return "bigint"; case TypeCode.Boolean: return "boolean"; case TypeCode.DateTime: return "timestamp"; case TypeCode.Byte: return "tinyint"; } if (type == typeof(Guid)) return "uuid"; if (type == typeof(DateTimeOffset)) return "timestamp"; if (type == typeof(Byte[])) return "blob"; if (type == typeof(ExtraPropertyDictionary)) return "map"; // 处理集合类型 if (type.IsGenericType) { var genericType = type.GetGenericTypeDefinition(); var elementType = type.GetGenericArguments()[0]; if (genericType == typeof(List<>)) return $"list<{GetCassandraType(elementType)}>"; if (genericType == typeof(HashSet<>)) return $"set<{GetCassandraType(elementType)}>"; if (genericType == typeof(Nullable<>)) return GetCassandraType(elementType); if (genericType == typeof(Dictionary<,>)) { var keyType = type.GetGenericArguments()[0]; var valueType = type.GetGenericArguments()[1]; return $"map<{GetCassandraType(keyType)}, {GetCassandraType(valueType)}>"; } } throw new NotSupportedException($"不支持的类型: {type.Name}"); } } }