84 lines
3.2 KiB
C#
84 lines
3.2 KiB
C#
|
|
using System.Reflection;
|
|||
|
|
using System.Text;
|
|||
|
|
using Cassandra;
|
|||
|
|
using System.ComponentModel.DataAnnotations;
|
|||
|
|
using JiShe.CollectBus.Common.Attributes;
|
|||
|
|
using Cassandra.Mapping;
|
|||
|
|
|
|||
|
|
namespace JiShe.CollectBus.Cassandra.Extensions
|
|||
|
|
{
|
|||
|
|
public static class SessionExtension
|
|||
|
|
{
|
|||
|
|
public static void CreateTable<TEntity>(this ISession session,string? defaultKeyspace=null) where TEntity : class
|
|||
|
|
{
|
|||
|
|
var type = typeof(TEntity);
|
|||
|
|
var tableAttribute = type.GetCustomAttribute<CassandraTableAttribute>();
|
|||
|
|
var tableName = tableAttribute?.Name ?? type.Name.ToLower();
|
|||
|
|
var tableKeyspace = tableAttribute?.Keyspace ?? defaultKeyspace;
|
|||
|
|
|
|||
|
|
var properties = type.GetProperties();
|
|||
|
|
var primaryKey = properties.FirstOrDefault(p => p.GetCustomAttribute<KeyAttribute>() != null);
|
|||
|
|
|
|||
|
|
if (primaryKey == null)
|
|||
|
|
{
|
|||
|
|
throw new InvalidOperationException($"No primary key defined for type {type.Name}");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var cql = new StringBuilder();
|
|||
|
|
cql.Append($"CREATE TABLE IF NOT EXISTS {tableKeyspace}.{tableName} (");
|
|||
|
|
|
|||
|
|
foreach (var prop in properties)
|
|||
|
|
{
|
|||
|
|
var ignoreAttribute = prop.GetCustomAttribute<CassandraIgnoreAttribute>();
|
|||
|
|
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()}))");
|
|||
|
|
|
|||
|
|
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.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(Dictionary<,>))
|
|||
|
|
{
|
|||
|
|
var keyType = type.GetGenericArguments()[0];
|
|||
|
|
var valueType = type.GetGenericArguments()[1];
|
|||
|
|
return $"map<{GetCassandraType(keyType)}, {GetCassandraType(valueType)}>";
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
throw new NotSupportedException($"不支持的类型: {type.Name}");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|