99 lines
3.8 KiB
C#
99 lines
3.8 KiB
C#
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<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 = session.Keyspace;
|
|
|
|
var properties = type.GetProperties();
|
|
|
|
// 分区键设置
|
|
var primaryKey = properties.FirstOrDefault(p => p.GetCustomAttribute<PartitionKeyAttribute>() != null);
|
|
|
|
if (primaryKey == null)
|
|
{
|
|
throw new InvalidOperationException($"No primary key defined for type {type.Name}");
|
|
}
|
|
|
|
// 集群键设置
|
|
var clusteringKeys = properties.Where(p => p.GetCustomAttribute<ClusteringKeyAttribute>() != 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<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()}){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<text,text>";
|
|
|
|
// 处理集合类型
|
|
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}");
|
|
}
|
|
|
|
|
|
}
|
|
}
|