注:达梦的驱动版本请使用2023第四季度及以后版本驱动才可以
ServiceStack介绍
ServiceStack官网: https://github.com/ServiceStack/ServiceStack
ServiceStack是一个开源的十分流行的WebService框架,引用其官网的介绍:“Service Stack is a high-performance .NET web services platform that simplifies the development of high-performance REST (JSON, XML, JSV, HTML, MsgPack, ProtoBuf, CSV) and WCF SOAP Web Services.”
“ServiceStack是一个高性能的.NET Web Service 平台,他能够简化开发高性能的REST (支持JSON,XML,JSV,HTML,MsgPack,ProtoBuf,CSV等消息格式)以及WCF SOAP风格的WebService”。
代码段
sql语句
CREATE TABLE "SYSDBA"."TestTab"
(
"Id" VARCHAR(200) NOT NULL,
"Name" VARCHAR(200),
NOT CLUSTER PRIMARY KEY("Id")) STORAGE(ON "MAIN", CLUSTERBTR) ;
Program.cs
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using NLog;
using NLog.Web;
using ServiceStack.DataAnnotations;
using ServiceStack.OrmLite;
namespace Yidea.Resource.Host
{
public class Program
{
public static void Main(string[] args)
{
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
var encoding = Encoding.GetEncoding("gb18030");
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");
var logger = NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
var dbFactory = new OrmLiteConnectionFactory("Server=192.15.1.17:5236; UserId=SYSDBA; PWD=SYSDBA; SCHEMA=SYSDBA;", GetSqlDialect());
var Db = dbFactory.CreateDbConnection();
Db.Open();
var aa = Db.Select<TestTab>(o => o.Id == "zzzzzz").First();
aa.Name = "xiugai";
Db.Save(aa);
/*
var company = Db.Select<Company>().ToList();
foreach (var item in company)
{
item.Name = item.Name + item.Id;
}
Db.SaveAll(company);
//var tab = new TestTab() { Id = "bb", Name = "bbbbbbb" };
//Db.Save(tab);
List<TestTab> list = Db.Select<TestTab>().ToList();
foreach (var item in list)
{
item.Name = item.Id + item.Name;
}
Db.SaveAll(list);*/
}
[Alias("vCompany")]
public class Company
{
[PrimaryKey]
[AutoIncrement]
public int Id { get; set; }
public string Code { get; set; }
public string Name { get; set; }
[Alias("EId")]
public int EnterpriseId { get; set; }
[Alias("Pid")]
public int? SuperiorCompanyId { get; set; }
[Alias("IsDisabled")]
public bool Disabled { get; set; }
[Alias("IdPath")]
public string Hierarchy { get; set; }
}
private static IOrmLiteDialectProvider GetSqlDialect()
{
var sqlProvider = new DmaProvider();
sqlProvider.GetStringConverter().UseUnicode = true;
sqlProvider.GetDateTimeConverter().DateStyle = DateTimeKind.Local;
return sqlProvider;
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseUrls("http://*:12345")
.UseKestrel(opt =>
{
opt.AddServerHeader = false;
opt.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(5);
})
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.ConfigureAppConfiguration((builderContext, config) =>
{
IHostingEnvironment env = builderContext.HostingEnvironment;
config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
config.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
})
.UseNLog();
}
}
DmaProvider.cs
using Dm;
using ServiceStack.DataAnnotations;
using ServiceStack;
using ServiceStack.OrmLite;
using ServiceStack.OrmLite.SqlServer.Converters;
using ServiceStack.OrmLite.SqlServer;
using ServiceStack.Text;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using ServiceStack.Data;
using System.Collections;
namespace Yidea.Resource.Host
{
public class DmaProvider : OrmLiteDialectProviderBase<DmaProvider>
{
public static DmaProvider Instance = new();
public DmaProvider()
{
base.AutoIncrementDefinition = "IDENTITY(1,1)";
base.SelectIdentitySql = "SELECT SCOPE_IDENTITY()";
base.InitColumnTypeMap();
RowVersionConverter = new SqlServerRowVersionConverter();
base.RegisterConverter<string>(new SqlServerStringConverter());
base.RegisterConverter<bool>(new SqlServerBoolConverter());
base.RegisterConverter<sbyte>(new SqlServerSByteConverter());
base.RegisterConverter<ushort>(new SqlServerUInt16Converter());
base.RegisterConverter<uint>(new SqlServerUInt32Converter());
base.RegisterConverter<ulong>(new SqlServerUInt64Converter());
base.RegisterConverter<float>(new SqlServerFloatConverter());
base.RegisterConverter<double>(new SqlServerDoubleConverter());
base.RegisterConverter<decimal>(new SqlServerDecimalConverter());
base.RegisterConverter<DateTime>(new SqlServerDateTimeConverter());
base.RegisterConverter<Guid>(new SqlServerGuidConverter());
base.RegisterConverter<byte[]>(new SqlServerByteArrayConverter());
this.Variables = new Dictionary<string, string>
{
{ OrmLiteVariables.SystemUtc, "SYSUTCDATETIME()" },
{ OrmLiteVariables.MaxText, "VARCHAR(MAX)" },
{ OrmLiteVariables.MaxTextUnicode, "NVARCHAR(MAX)" },
{ OrmLiteVariables.True, SqlBool(true) },
{ OrmLiteVariables.False, SqlBool(false) },
};
}
public override string GetQuotedValue(string paramValue)
{
return (StringConverter.UseUnicode ? "N'" : "'") + paramValue.Replace("'", "''") + "'";
}
public override IDbConnection CreateConnection(string connectionString, Dictionary<string, string> options)
{
DmConnection conn = new DmConnection();
conn.ConnectionString = connectionString;
return conn;
}
public override SqlExpression<T> SqlExpression<T>() => new SqlServerExpression<T>(this);
// public override IDbDataParameter CreateParam() => new SqlParameter();
public override IDbDataParameter CreateParam() => new DmParameter();
private const string DefaultSchema = "dbo";
public override string ToTableNamesStatement(string schema)
{
var sql = "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE'";
return sql + " AND TABLE_SCHEMA = {0}".SqlFmt(this, schema ?? DefaultSchema);
}
public override string ToTableNamesWithRowCountsStatement(bool live, string schema)
{
var schemaSql = " AND s.Name = {0}".SqlFmt(this, schema ?? DefaultSchema);
var sql = @"SELECT t.NAME, p.rows FROM sys.tables t INNER JOIN sys.schemas s ON t.schema_id = s.schema_id
INNER JOIN sys.indexes i ON t.OBJECT_ID = i.object_id
INNER JOIN sys.partitions p ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id
WHERE t.is_ms_shipped = 0 " + schemaSql + " GROUP BY t.NAME, p.Rows";
return sql;
}
//public override List<string> GetSchemas(IDbCommand dbCmd)
//{
// var sql = "SELECT DISTINCT TABLE_SCHEMA FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE'";
// return dbCmd.SqlColumn<string>(sql);
//}
//public override Dictionary<string, List<string>> GetSchemaTables(IDbCommand dbCmd)
//{
// var sql = "SELECT TABLE_SCHEMA, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE'";
// return dbCmd.Lookup<string, string>(sql);
//}
public override bool DoesSchemaExist(IDbCommand dbCmd, string schemaName)
{
var sql = $"SELECT count(*) FROM sys.schemas WHERE name = '{schemaName.SqlParam()}'";
var result = dbCmd.ExecLongScalar(sql);
return result > 0;
}
//public override async Task<bool> DoesSchemaExistAsync(IDbCommand dbCmd, string schemaName, CancellationToken token = default)
//{
// var sql = $"SELECT count(*) FROM sys.schemas WHERE name = '{schemaName.SqlParam()}'";
// var result = await dbCmd.ExecLongScalarAsync(sql, token);
// return result > 0;
//}
public override string ToCreateSchemaStatement(string schemaName)
{
var sql = $"CREATE SCHEMA [{GetSchemaName(schemaName)}]";
return sql;
}
//public override string ToCreateSavePoint(string name) => $"SAVE TRANSACTION {name}";
//public override string ToReleaseSavePoint(string name) => null;
//public override string ToRollbackSavePoint(string name) => $"ROLLBACK TRANSACTION {name}";
public override bool DoesTableExist(IDbCommand dbCmd, string tableName, string schema = null)
{
var sql = "SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = {0}"
.SqlFmt(this, tableName);
if (schema != null)
sql += " AND TABLE_SCHEMA = {0}".SqlFmt(this, schema);
else
sql += " AND TABLE_SCHEMA <> 'Security'";
var result = dbCmd.ExecLongScalar(sql);
return result > 0;
}
//public override async Task<bool> DoesTableExistAsync(IDbCommand dbCmd, string tableName, string schema = null, CancellationToken token = default)
//{
// var sql = "SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = {0}"
// .SqlFmt(this, tableName);
// if (schema != null)
// sql += " AND TABLE_SCHEMA = {0}".SqlFmt(this, schema);
// else
// sql += " AND TABLE_SCHEMA <> 'Security'";
// var result = await dbCmd.ExecLongScalarAsync(sql, token);
// return result > 0;
//}
public override bool DoesColumnExist(IDbConnection db, string columnName, string tableName, string schema = null)
{
var sql = "SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @tableName AND COLUMN_NAME = @columnName"
.SqlFmt(this, tableName, columnName);
if (schema != null)
sql += " AND TABLE_SCHEMA = @schema";
var result = db.SqlScalar<long>(sql, new { tableName, columnName, schema });
return result > 0;
}
//public override async Task<bool> DoesColumnExistAsync(IDbConnection db, string columnName, string tableName, string schema = null,
// CancellationToken token = default)
//{
// var sql = "SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @tableName AND COLUMN_NAME = @columnName"
// .SqlFmt(this, tableName, columnName);
// if (schema != null)
// sql += " AND TABLE_SCHEMA = @schema";
// var result = await db.SqlScalarAsync<long>(sql, new { tableName, columnName, schema }, token: token);
// return result > 0;
//}
//public override string GetForeignKeyOnDeleteClause(ForeignKeyConstraint foreignKey)
//{
// return "RESTRICT" == (foreignKey.OnDelete ?? "").ToUpper()
// ? ""
// : base.GetForeignKeyOnDeleteClause(foreignKey);
//}
//public override string GetForeignKeyOnUpdateClause(ForeignKeyConstraint foreignKey)
//{
// return "RESTRICT" == (foreignKey.OnUpdate ?? "").ToUpper()
// ? ""
// : base.GetForeignKeyOnUpdateClause(foreignKey);
//}
public override string GetDropForeignKeyConstraints(ModelDefinition modelDef)
{
//TODO: find out if this should go in base class?
var sb = StringBuilderCache.Allocate();
foreach (var fieldDef in modelDef.FieldDefinitions)
{
if (fieldDef.ForeignKey != null)
{
var foreignKeyName = fieldDef.ForeignKey.GetForeignKeyName(
modelDef,
OrmLiteUtils.GetModelDefinition(fieldDef.ForeignKey.ReferenceType),
NamingStrategy,
fieldDef);
var tableName = GetQuotedTableName(modelDef);
sb.AppendLine($"IF EXISTS (SELECT name FROM sys.foreign_keys WHERE name = '{foreignKeyName}')");
sb.AppendLine("BEGIN");
sb.AppendLine($" ALTER TABLE {tableName} DROP {foreignKeyName};");
sb.AppendLine("END");
}
}
return StringBuilderCache.ReturnAndFree(sb);
}
//public override string ToAddColumnStatement(string schema, string table, FieldDefinition fieldDef) =>
// $"ALTER TABLE {GetQuotedTableName(table, schema)} ADD {GetColumnDefinition(fieldDef)};";
//public override string ToAlterColumnStatement(string schema, string table, FieldDefinition fieldDef) =>
// $"ALTER TABLE {GetQuotedTableName(table, schema)} ALTER COLUMN {GetColumnDefinition(fieldDef)};";
//public override string ToChangeColumnNameStatement(string schema, string table, FieldDefinition fieldDef, string oldColumn)
//{
// var modelName = NamingStrategy.GetTableName(table);
// var objectName = $"{modelName}.{oldColumn}";
// return $"EXEC sp_rename {GetQuotedValue(objectName)}, {GetQuotedValue(fieldDef.FieldName)}, {GetQuotedValue("COLUMN")};";
//}
//public override string ToRenameColumnStatement(string schema, string table, string oldColumn, string newColumn)
//{
// var modelName = NamingStrategy.GetTableName(table);
// var objectName = $"{modelName}.{GetQuotedColumnName(oldColumn)}";
// return $"EXEC sp_rename {GetQuotedValue(objectName)}, {GetQuotedColumnName(newColumn)}, 'COLUMN';";
//}
protected virtual string GetAutoIncrementDefinition(FieldDefinition fieldDef)
{
return AutoIncrementDefinition;
}
public override string GetAutoIdDefaultValue(FieldDefinition fieldDef)
{
return fieldDef.FieldType == typeof(Guid)
? "newid()"
: null;
}
public override string GetColumnDefinition(FieldDefinition fieldDef)
{
// https://msdn.microsoft.com/en-us/library/ms182776.aspx
if (fieldDef.IsRowVersion)
return $"{fieldDef.FieldName} rowversion NOT NULL";
var fieldDefinition = ResolveFragment(fieldDef.CustomFieldDefinition) ??
GetColumnTypeDefinition(fieldDef.ColumnType, fieldDef.FieldLength, fieldDef.Scale);
var sql = StringBuilderCache.Allocate();
sql.Append($"{GetQuotedColumnName(fieldDef.FieldName)} {fieldDefinition}");
if (fieldDef.FieldType == typeof(string))
{
// https://msdn.microsoft.com/en-us/library/ms184391.aspx
var collation = fieldDef.PropertyInfo?.FirstAttribute<SqlServerCollateAttribute>()?.Collation;
if (!string.IsNullOrEmpty(collation))
{
sql.Append($" COLLATE {collation}");
}
}
if (fieldDef.IsPrimaryKey)
{
sql.Append(" PRIMARY KEY");
if (fieldDef.IsNonClustered)
sql.Append(" NONCLUSTERED");
if (fieldDef.AutoIncrement)
{
sql.Append(" ").Append(GetAutoIncrementDefinition(fieldDef));
}
}
else
{
sql.Append(fieldDef.IsNullable ? " NULL" : " NOT NULL");
}
if (fieldDef.IsUniqueConstraint)
{
sql.Append(" UNIQUE");
}
var defaultValue = GetDefaultValue(fieldDef);
if (!string.IsNullOrEmpty(defaultValue))
{
sql.AppendFormat(DefaultValueFormat, defaultValue);
}
return StringBuilderCache.ReturnAndFree(sql);
}
//public override void BulkInsert<T>(IDbConnection db, IEnumerable<T> objs, BulkInsertConfig config = null)
//{
// config ??= new();
// //if (config.Mode == BulkInsertMode.Sql)
// //{
// // base.BulkInsert(db, objs, config);
// // return;
// //}
// var sqlConn = (SqlConnection)db.ToDbConnection();
// using var bulkCopy = new SqlBulkCopy(sqlConn);
// var modelDef = ModelDefinition<T>.Definition;
// bulkCopy.BatchSize = config.BatchSize;
// bulkCopy.DestinationTableName = modelDef.ModelName;
// var table = new DataTable();
// var fieldDefs = GetInsertFieldDefinitions(modelDef, insertFields: config.InsertFields);
// foreach (var fieldDef in fieldDefs)
// {
// if (ShouldSkipInsert(fieldDef) && !fieldDef.AutoId)
// continue;
// var columnName = NamingStrategy.GetColumnName(fieldDef.FieldName);
// bulkCopy.ColumnMappings.Add(columnName, columnName);
// var converter = GetConverterBestMatch(fieldDef);
// var colType = converter.DbType switch
// {
// DbType.String => typeof(string),
// DbType.Int32 => typeof(int),
// DbType.Int64 => typeof(long),
// _ => Nullable.GetUnderlyingType(fieldDef.FieldType) ?? fieldDef.FieldType
// };
// table.Columns.Add(columnName, colType);
// }
// foreach (var obj in objs)
// {
// var row = table.NewRow();
// foreach (var fieldDef in fieldDefs)
// {
// if (ShouldSkipInsert(fieldDef) && !fieldDef.AutoId)
// continue;
// var value = fieldDef.AutoId
// ? GetInsertDefaultValue(fieldDef)
// : fieldDef.GetValue(obj);
// var converter = GetConverterBestMatch(fieldDef);
// var dbValue = converter.ToDbValue(fieldDef.FieldType, value);
// var columnName = NamingStrategy.GetColumnName(fieldDef.FieldName);
// dbValue ??= DBNull.Value;
// row[columnName] = dbValue;
// }
// table.Rows.Add(row);
// }
// bulkCopy.WriteToServer(table);
//}
public override string ToInsertRowStatement(IDbCommand cmd, object objWithProperties, ICollection<string> insertFields = null)
{
var sbColumnNames = StringBuilderCache.Allocate();
var sbColumnValues = StringBuilderCacheAlt.Allocate();
var sbReturningColumns = StringBuilderCacheAlt.Allocate();
var tableType = objWithProperties.GetType();
var modelDef = GetModel(tableType);
var fieldDefs = GetInsertFieldDefinitions(modelDef, insertFields);
foreach (var fieldDef in fieldDefs)
{
if (ShouldReturnOnInsert(modelDef, fieldDef))
{
if (sbReturningColumns.Length > 0)
sbReturningColumns.Append(",");
sbReturningColumns.Append("INSERTED." + GetQuotedColumnName(fieldDef.FieldName));
}
if (ShouldSkipInsert(fieldDef) && !fieldDef.AutoId)
continue;
if (sbColumnNames.Length > 0)
sbColumnNames.Append(",");
if (sbColumnValues.Length > 0)
sbColumnValues.Append(",");
try
{
sbColumnNames.Append(GetQuotedColumnName(fieldDef.FieldName));
sbColumnValues.Append(this.GetParam(SanitizeFieldNameForParamName(fieldDef.FieldName)));
AddParameter(cmd, fieldDef);
}
catch (Exception ex)
{
Log.Error("ERROR in ToInsertRowStatement(): " + ex.Message, ex);
throw;
}
}
foreach (var fieldDef in modelDef.AutoIdFields) // need to include any AutoId fields that weren't included
{
if (fieldDefs.Contains(fieldDef))
continue;
if (sbReturningColumns.Length > 0)
sbReturningColumns.Append(",");
sbReturningColumns.Append("INSERTED." + GetQuotedColumnName(fieldDef.FieldName));
}
var strReturning = StringBuilderCacheAlt.ReturnAndFree(sbReturningColumns);
strReturning = strReturning.Length > 0 ? "OUTPUT " + strReturning + " " : "";
var sql = sbColumnNames.Length > 0
? $"INSERT INTO {GetQuotedTableName(modelDef)} ({StringBuilderCache.ReturnAndFree(sbColumnNames)}) " +
strReturning +
$"VALUES ({StringBuilderCacheAlt.ReturnAndFree(sbColumnValues)})"
: $"INSERT INTO {GetQuotedTableName(modelDef)} {strReturning} DEFAULT VALUES";
return sql;
}
protected string Sequence(string schema, string sequence)
{
if (schema == null)
return GetQuotedName(sequence);
var escapedSchema = NamingStrategy.GetSchemaName(schema)
.Replace(".", "\".\"");
return GetQuotedName(escapedSchema)
+ "."
+ GetQuotedName(sequence);
}
protected override bool ShouldSkipInsert(FieldDefinition fieldDef) =>
fieldDef.ShouldSkipInsert() || fieldDef.AutoId;
protected virtual bool ShouldReturnOnInsert(ModelDefinition modelDef, FieldDefinition fieldDef) =>
fieldDef.ReturnOnInsert || (fieldDef.IsPrimaryKey && fieldDef.AutoIncrement && HasInsertReturnValues(modelDef)) || fieldDef.AutoId;
public override bool HasInsertReturnValues(ModelDefinition modelDef) =>
modelDef.FieldDefinitions.Any(x => x.ReturnOnInsert || (x.AutoId && x.FieldType == typeof(Guid)));
protected virtual bool SupportsSequences(FieldDefinition fieldDef) => false;
//public override void EnableIdentityInsert<T>(IDbCommand cmd)
//{
// var tableName = cmd.GetDialectProvider().GetQuotedTableName(ModelDefinition<T>.Definition);
// cmd.ExecNonQuery($"SET IDENTITY_INSERT {tableName} ON");
//}
//public override Task EnableIdentityInsertAsync<T>(IDbCommand cmd, CancellationToken token = default)
//{
// var tableName = cmd.GetDialectProvider().GetQuotedTableName(ModelDefinition<T>.Definition);
// return cmd.ExecNonQueryAsync($"SET IDENTITY_INSERT {tableName} ON", null, token);
//}
//public override void DisableIdentityInsert<T>(IDbCommand cmd)
//{
// var tableName = cmd.GetDialectProvider().GetQuotedTableName(ModelDefinition<T>.Definition);
// cmd.ExecNonQuery($"SET IDENTITY_INSERT {tableName} OFF");
//}
//public override Task DisableIdentityInsertAsync<T>(IDbCommand cmd, CancellationToken token = default)
//{
// var tableName = cmd.GetDialectProvider().GetQuotedTableName(ModelDefinition<T>.Definition);
// return cmd.ExecNonQueryAsync($"SET IDENTITY_INSERT {tableName} OFF", null, token);
//}
public override bool PrepareParameterizedUpdateStatement<T>(IDbCommand cmd, ICollection<string> updateFields = null)
{
var sql = StringBuilderCache.Allocate();
var sqlFilter = StringBuilderCacheAlt.Allocate();
var modelDef = ModelDefinition<T>.Definition;
var hadRowVersion = false;
var updateAllFields = updateFields == null || updateFields.Count == 0;
cmd.Parameters.Clear();
foreach (var fieldDef in modelDef.FieldDefinitions)
{
if (fieldDef.ShouldSkipUpdate())
continue;
try
{
if ((fieldDef.IsPrimaryKey || fieldDef.IsRowVersion) && updateAllFields)
{
if (sqlFilter.Length > 0)
sqlFilter.Append(" AND ");
AppendFieldCondition(sqlFilter, fieldDef, cmd);
if (fieldDef.IsRowVersion)
hadRowVersion = true;
continue;
}
if (!updateAllFields && !updateFields.Contains(fieldDef.Name, StringComparer.OrdinalIgnoreCase))
continue;
if (sql.Length > 0)
sql.Append(", ");
sql
.Append(GetQuotedColumnName(fieldDef.FieldName))
.Append("=")
.Append(this.GetParam(SanitizeFieldNameForParamName(fieldDef.FieldName)));
AddParameter(cmd, fieldDef);
}
catch (Exception ex)
{
OrmLiteUtils.HandleException(ex, "ERROR in PrepareParameterizedUpdateStatement(): " + ex.Message);
}
}
if (sql.Length > 0)
{
var strFilter = StringBuilderCacheAlt.ReturnAndFree(sqlFilter);
cmd.CommandText = $"UPDATE {GetQuotedTableName(modelDef)} " +
$"SET {StringBuilderCache.ReturnAndFree(sql)} {(strFilter.Length > 0 ? "WHERE " + strFilter : "")}";
cmd.CommandText = cmd.CommandText.ReplaceAll("@", ":");
}
else
{
cmd.CommandText = "";
}
return hadRowVersion;
}
public void SetValue(object instance, object value)
{
if (instance is IDictionary d)
{
d[Name] = value;
return;
}
this.SetValueFn?.Invoke(instance, value);
}
public string Name { get; set; }
public SetMemberDelegate SetValueFn { get; set; }
public override void SetParameterValues<T>(IDbCommand dbCmd, object obj)
{
var modelDef = GetModel(typeof(T));
var fieldMap = GetFieldDefinitionMap(modelDef);
foreach (IDataParameter p in dbCmd.Parameters)
{
var fieldName = this.ToFieldName(p.ParameterName);
fieldMap.TryGetValue(fieldName, out var fieldDef);
if (fieldDef == null)
{
if (ParamNameFilter != null)
{
fieldDef = modelDef.GetFieldDefinition(name =>
string.Equals(ParamNameFilter(name), fieldName, StringComparison.OrdinalIgnoreCase));
}
if (fieldDef == null)
throw new ArgumentException($"Field Definition '{fieldName}' was not found");
}
if (fieldDef.AutoId && p.Value != null)
{
var existingId = fieldDef.GetValue(obj);
if (existingId is Guid existingGuid && existingGuid != default(Guid))
{
p.Value = existingGuid; // Use existing value if not default
}
//fieldDef.SetValue(obj, p.Value); //Auto populate default values
continue;
}
SetParameterValue(fieldDef, p, obj);
}
dbCmd.CommandText = dbCmd.CommandText.ReplaceAll("@", ":");
var rowsUpdated = dbCmd.ExecNonQuery();
}
public virtual void SetParameterValue(FieldDefinition fieldDef, IDataParameter p, object obj)
{
var value = GetValueOrDbNull(fieldDef, obj);
p.Value = value;
SetParameterSize(fieldDef, p);
}
protected virtual void SetParameterSize(FieldDefinition fieldDef, IDataParameter p)
{
if (p.Value is string s && p is IDbDataParameter dataParam && dataParam.Size > 0 && s.Length > dataParam.Size)
{
// db param Size set in StringConverter
dataParam.Size = s.Length;
}
}
protected virtual object GetValue(FieldDefinition fieldDef, object obj)
{
return GetFieldValue(fieldDef, fieldDef.GetValue(obj));
}
public object GetFieldValue(FieldDefinition fieldDef, object value)
{
if (value == null)
return null;
var converter = GetConverterBestMatch(fieldDef);
try
{
return converter.ToDbValue(fieldDef.FieldType, value);
}
catch (Exception ex)
{
Log.Error($"Error in {converter.GetType().Name}.ToDbValue() for field '{fieldDef.Name}' of Type '{fieldDef.FieldType}' with value '{value.GetType().Name}'", ex);
throw;
}
}
public object GetFieldValue(Type fieldType, object value)
{
if (value == null)
return null;
var converter = GetConverterBestMatch(fieldType);
try
{
return converter.ToDbValue(fieldType, value);
}
catch (Exception ex)
{
Log.Error($"Error in {converter.GetType().Name}.ToDbValue() for field of Type '{fieldType}' with value '{value.GetType().Name}'", ex);
throw;
}
}
protected virtual object GetValueOrDbNull(FieldDefinition fieldDef, object obj)
{
var value = GetValue(fieldDef, obj);
if (value == null)
return DBNull.Value;
return value;
}
protected virtual object GetQuotedValueOrDbNull<T>(FieldDefinition fieldDef, object obj)
{
var value = fieldDef.GetValue(obj);
if (value == null)
return DBNull.Value;
var unquotedVal = GetQuotedValue(value, fieldDef.FieldType)
.TrimStart('\'').TrimEnd('\''); ;
if (string.IsNullOrEmpty(unquotedVal))
return DBNull.Value;
return unquotedVal;
}
public override string ToUpdateStatement<T>(IDbCommand dbCmd, T item, ICollection<string> updateFields = null)
{
return base.ToUpdateStatement(dbCmd, item, updateFields);
}
public override void PrepareParameterizedInsertStatement<T>(IDbCommand cmd, ICollection<string> insertFields = null)
{
var sbColumnNames = StringBuilderCache.Allocate();
var sbColumnValues = StringBuilderCacheAlt.Allocate();
var sbReturningColumns = StringBuilderCacheAlt.Allocate();
var modelDef = OrmLiteUtils.GetModelDefinition(typeof(T));
cmd.Parameters.Clear();
var fieldDefs = GetInsertFieldDefinitions(modelDef, insertFields);
foreach (var fieldDef in fieldDefs)
{
if (ShouldReturnOnInsert(modelDef, fieldDef))
{
if (sbReturningColumns.Length > 0)
sbReturningColumns.Append(",");
sbReturningColumns.Append("INSERTED." + GetQuotedColumnName(fieldDef.FieldName));
}
if ((ShouldSkipInsert(fieldDef) && !fieldDef.AutoId))
continue;
if (sbColumnNames.Length > 0)
sbColumnNames.Append(",");
if (sbColumnValues.Length > 0)
sbColumnValues.Append(",");
try
{
sbColumnNames.Append(GetQuotedColumnName(fieldDef.FieldName));
if (SupportsSequences(fieldDef))
{
sbColumnValues.Append("NEXT VALUE FOR " + Sequence(NamingStrategy.GetSchemaName(modelDef), fieldDef.Sequence));
}
else
{
sbColumnValues.Append(this.GetParam(SanitizeFieldNameForParamName(fieldDef.FieldName)));
AddParameter(cmd, fieldDef);
}
}
catch (Exception ex)
{
Log.Error("ERROR in PrepareParameterizedInsertStatement(): " + ex.Message, ex);
throw;
}
}
foreach (var fieldDef in modelDef.AutoIdFields) // need to include any AutoId fields that weren't included
{
if (fieldDefs.Contains(fieldDef))
continue;
if (sbReturningColumns.Length > 0)
sbReturningColumns.Append(",");
sbReturningColumns.Append("INSERTED." + GetQuotedColumnName(fieldDef.FieldName));
}
var strReturning = StringBuilderCacheAlt.ReturnAndFree(sbReturningColumns);
strReturning = strReturning.Length > 0 ? "OUTPUT " + strReturning + " " : "";
cmd.CommandText = sbColumnNames.Length > 0
? $"INSERT INTO {GetQuotedTableName(modelDef)} ({StringBuilderCache.ReturnAndFree(sbColumnNames)}) {strReturning}" +
$"VALUES ({StringBuilderCacheAlt.ReturnAndFree(sbColumnValues)})"
: $"INSERT INTO {GetQuotedTableName(modelDef)}{strReturning} DEFAULT VALUES";
cmd.CommandText = cmd.CommandText.ReplaceAll("@", ":");
}
//public override void PrepareParameterizedInsertStatement<T>(IDbCommand cmd, ICollection<string> insertFields = null,
// Func<FieldDefinition, bool> shouldInclude = null)
//{
// var sbColumnNames = StringBuilderCache.Allocate();
// var sbColumnValues = StringBuilderCacheAlt.Allocate();
// var sbReturningColumns = StringBuilderCacheAlt.Allocate();
// var modelDef = OrmLiteUtils.GetModelDefinition(typeof(T));
// cmd.Parameters.Clear();
// var fieldDefs = GetInsertFieldDefinitions(modelDef, insertFields);
// foreach (var fieldDef in fieldDefs)
// {
// if (ShouldReturnOnInsert(modelDef, fieldDef))
// {
// if (sbReturningColumns.Length > 0)
// sbReturningColumns.Append(",");
// sbReturningColumns.Append("INSERTED." + GetQuotedColumnName(fieldDef.FieldName));
// }
// if ((ShouldSkipInsert(fieldDef) && !fieldDef.AutoId)
// && shouldInclude?.Invoke(fieldDef) != true)
// continue;
// if (sbColumnNames.Length > 0)
// sbColumnNames.Append(",");
// if (sbColumnValues.Length > 0)
// sbColumnValues.Append(",");
// try
// {
// sbColumnNames.Append(GetQuotedColumnName(fieldDef.FieldName));
// if (SupportsSequences(fieldDef))
// {
// sbColumnValues.Append("NEXT VALUE FOR " + Sequence(NamingStrategy.GetSchemaName(modelDef), fieldDef.Sequence));
// }
// else
// {
// sbColumnValues.Append(this.GetParam(SanitizeFieldNameForParamName(fieldDef.FieldName), fieldDef.CustomInsert));
// AddParameter(cmd, fieldDef);
// }
// }
// catch (Exception ex)
// {
// Log.Error("ERROR in PrepareParameterizedInsertStatement(): " + ex.Message, ex);
// throw;
// }
// }
// foreach (var fieldDef in modelDef.AutoIdFields) // need to include any AutoId fields that weren't included
// {
// if (fieldDefs.Contains(fieldDef))
// continue;
// if (sbReturningColumns.Length > 0)
// sbReturningColumns.Append(",");
// sbReturningColumns.Append("INSERTED." + GetQuotedColumnName(fieldDef.FieldName));
// }
// var strReturning = StringBuilderCacheAlt.ReturnAndFree(sbReturningColumns);
// strReturning = strReturning.Length > 0 ? "OUTPUT " + strReturning + " " : "";
// cmd.CommandText = sbColumnNames.Length > 0
// ? $"INSERT INTO {GetQuotedTableName(modelDef)} ({StringBuilderCache.ReturnAndFree(sbColumnNames)}) {strReturning}" +
// $"VALUES ({StringBuilderCacheAlt.ReturnAndFree(sbColumnValues)})"
// : $"INSERT INTO {GetQuotedTableName(modelDef)}{strReturning} DEFAULT VALUES";
//}
//public override void PrepareParameterizedInsertStatement<T>(IDbCommand cmd, ICollection<string> insertFields = null,
// Func<FieldDefinition, bool> shouldInclude = null)
//{
// var sbColumnNames = StringBuilderCache.Allocate();
// var sbColumnValues = StringBuilderCacheAlt.Allocate();
// var sbReturningColumns = StringBuilderCacheAlt.Allocate();
// var modelDef = OrmLiteUtils.GetModelDefinition(typeof(T));
// cmd.Parameters.Clear();
// var fieldDefs = GetInsertFieldDefinitions(modelDef, insertFields);
// foreach (var fieldDef in fieldDefs)
// {
// if (ShouldReturnOnInsert(modelDef, fieldDef))
// {
// if (sbReturningColumns.Length > 0)
// sbReturningColumns.Append(",");
// sbReturningColumns.Append("INSERTED." + GetQuotedColumnName(fieldDef.FieldName));
// }
// if ((ShouldSkipInsert(fieldDef) && !fieldDef.AutoId)
// && shouldInclude?.Invoke(fieldDef) != true)
// continue;
// if (sbColumnNames.Length > 0)
// sbColumnNames.Append(",");
// if (sbColumnValues.Length > 0)
// sbColumnValues.Append(",");
// try
// {
// sbColumnNames.Append(GetQuotedColumnName(fieldDef.FieldName));
// if (SupportsSequences(fieldDef))
// {
// sbColumnValues.Append("NEXT VALUE FOR " + Sequence(NamingStrategy.GetSchemaName(modelDef), fieldDef.Sequence));
// }
// else
// {
// sbColumnValues.Append(this.GetParam(SanitizeFieldNameForParamName(fieldDef.FieldName), fieldDef.CustomInsert));
// AddParameter(cmd, fieldDef);
// }
// }
// catch (Exception ex)
// {
// Log.Error("ERROR in PrepareParameterizedInsertStatement(): " + ex.Message, ex);
// throw;
// }
// }
// foreach (var fieldDef in modelDef.AutoIdFields) // need to include any AutoId fields that weren't included
// {
// if (fieldDefs.Contains(fieldDef))
// continue;
// if (sbReturningColumns.Length > 0)
// sbReturningColumns.Append(",");
// sbReturningColumns.Append("INSERTED." + GetQuotedColumnName(fieldDef.FieldName));
// }
// var strReturning = StringBuilderCacheAlt.ReturnAndFree(sbReturningColumns);
// strReturning = strReturning.Length > 0 ? "OUTPUT " + strReturning + " " : "";
// cmd.CommandText = sbColumnNames.Length > 0
// ? $"INSERT INTO {GetQuotedTableName(modelDef)} ({StringBuilderCache.ReturnAndFree(sbColumnNames)}) {strReturning}" +
// $"VALUES ({StringBuilderCacheAlt.ReturnAndFree(sbColumnValues)})"
// : $"INSERT INTO {GetQuotedTableName(modelDef)}{strReturning} DEFAULT VALUES";
//}
public override void PrepareInsertRowStatement<T>(IDbCommand dbCmd, Dictionary<string, object> args)
{
var sbColumnNames = StringBuilderCache.Allocate();
var sbColumnValues = StringBuilderCacheAlt.Allocate();
var sbReturningColumns = StringBuilderCacheAlt.Allocate();
var modelDef = OrmLiteUtils.GetModelDefinition(typeof(T));
dbCmd.Parameters.Clear();
//foreach (var entry in args)
//{
// var fieldDef = modelDef.AssertFieldDefinition(entry.Key);
// if (ShouldReturnOnInsert(modelDef, fieldDef))
// {
// if (sbReturningColumns.Length > 0)
// sbReturningColumns.Append(",");
// sbReturningColumns.Append("INSERTED." + GetQuotedColumnName(fieldDef.FieldName));
// }
// if (ShouldSkipInsert(fieldDef) && !fieldDef.AutoId)
// continue;
// var value = entry.Value;
// if (sbColumnNames.Length > 0)
// sbColumnNames.Append(",");
// if (sbColumnValues.Length > 0)
// sbColumnValues.Append(",");
// try
// {
// sbColumnNames.Append(GetQuotedColumnName(fieldDef.FieldName));
// sbColumnValues.Append(this.GetInsertParam(dbCmd, value, fieldDef));
// }
// catch (Exception ex)
// {
// Log.Error("ERROR in PrepareInsertRowStatement(): " + ex.Message, ex);
// throw;
// }
//}
//var strReturning = StringBuilderCacheAlt.ReturnAndFree(sbReturningColumns);
//strReturning = strReturning.Length > 0 ? "OUTPUT " + strReturning + " " : "";
//dbCmd.CommandText = sbColumnNames.Length > 0
// ? $"INSERT INTO {GetQuotedTableName(modelDef)} ({StringBuilderCache.ReturnAndFree(sbColumnNames)}) {strReturning}" +
// $"VALUES ({StringBuilderCacheAlt.ReturnAndFree(sbColumnValues)})"
// : $"INSERT INTO {GetQuotedTableName(modelDef)} {strReturning}DEFAULT VALUES";
}
public enum QueryType
{
Select,
Single,
Scalar,
}
public override FieldDefinition[] GetInsertFieldDefinitions(ModelDefinition modelDef, ICollection<string> insertFields)
{
return base.GetInsertFieldDefinitions(modelDef, insertFields);
}
protected override object GetInsertDefaultValue(FieldDefinition fieldDef)
{
return base.GetInsertDefaultValue(fieldDef);
}
public override string ToInsertStatement<T>(IDbCommand dbCmd, T item, ICollection<string> insertFields = null)
{
return base.ToInsertStatement(dbCmd, item, insertFields);
}
public override string ToSelectStatement(Type tableType, string sqlFilter, params object[] filterParams)
{
var aa = base.ToSelectStatement(tableType, sqlFilter, filterParams).ReplaceAll("@", ":");
return aa;
}
public override string ToSelectStatement(ModelDefinition modelDef, string selectExpression, string bodyExpression, string orderByExpression = null, int? offset = null, int? rows = null)
{
var aa = base.ToSelectStatement(modelDef, selectExpression, bodyExpression, orderByExpression, offset, rows).ReplaceAll("@", ":");
return aa;
}
//public override string ToSelectStatement(QueryType queryType, ModelDefinition modelDef,
// string selectExpression,
// string bodyExpression,
// string orderByExpression = null,
// int? offset = null,
// int? rows = null,
// ISet<string> tags = null)
//{
// var sb = StringBuilderCache.Allocate();
// ApplyTags(sb, tags);
// sb.Append(selectExpression)
// .Append(bodyExpression);
// if (!offset.HasValue && !rows.HasValue || (queryType != QueryType.Select && rows != 1))
// return StringBuilderCache.ReturnAndFree(sb) + orderByExpression;
// if (offset is < 0)
// throw new ArgumentException($"Skip value:'{offset.Value}' must be>=0");
// if (rows is < 0)
// throw new ArgumentException($"Rows value:'{rows.Value}' must be>=0");
// var skip = offset ?? 0;
// var take = rows ?? int.MaxValue;
// var selectType = selectExpression.StartsWithIgnoreCase("SELECT DISTINCT") ? "SELECT DISTINCT" : "SELECT";
// //avoid Windowing function if unnecessary
// if (skip == 0)
// {
// var sql = StringBuilderCache.ReturnAndFree(sb) + orderByExpression;
// return SqlTop(sql, take, selectType);
// }
// // Required because ordering is done by Windowing function
// if (string.IsNullOrEmpty(orderByExpression))
// {
// if (modelDef.PrimaryKey == null)
// throw new ApplicationException("Malformed model, no PrimaryKey defined");
// orderByExpression = $"ORDER BY {this.GetQuotedColumnName(modelDef, modelDef.PrimaryKey)}";
// }
// var row = take == int.MaxValue ? take : skip + take;
// var ret = $"SELECT * FROM (SELECT {selectExpression.Substring(selectType.Length)}, ROW_NUMBER() OVER ({orderByExpression}) As RowNum {bodyExpression}) AS RowConstrainedResult WHERE RowNum > {skip} AND RowNum <= {row}";
// return ret;
//}
protected static string SqlTop(string sql, int take, string selectType = null)
{
selectType ??= sql.StartsWithIgnoreCase("SELECT DISTINCT") ? "SELECT DISTINCT" : "SELECT";
if (take == int.MaxValue)
return sql;
if (sql.Length < "SELECT".Length)
return sql;
return sql.Substring(0, sql.IndexOf(selectType)) + selectType + " TOP " + take + sql.Substring(sql.IndexOf(selectType) + selectType.Length);
}
//SELECT without RowNum and prefer aliases to be able to use in SELECT IN () Reference Queries
public static string UseAliasesOrStripTablePrefixes(string selectExpression)
{
if (selectExpression.IndexOf('.') < 0)
return selectExpression;
var sb = StringBuilderCache.Allocate();
var selectToken = selectExpression.SplitOnFirst(' ');
var tokens = selectToken[1].Split(',');
foreach (var token in tokens)
{
if (sb.Length > 0)
sb.Append(", ");
var field = token.Trim();
var aliasParts = field.SplitOnLast(' ');
if (aliasParts.Length > 1)
{
sb.Append(" " + aliasParts[aliasParts.Length - 1]);
continue;
}
var parts = field.SplitOnLast('.');
if (parts.Length > 1)
{
sb.Append(" " + parts[parts.Length - 1]);
}
else
{
sb.Append(" " + field);
}
}
var sqlSelect = selectToken[0] + " " + StringBuilderCache.ReturnAndFree(sb).Trim();
return sqlSelect;
}
public override string GetLoadChildrenSubSelect<From>(SqlExpression<From> expr)
{
if (!expr.OrderByExpression.IsNullOrEmpty() && expr.Rows == null)
{
var modelDef = expr.ModelDef;
expr.Select(this.GetQuotedColumnName(modelDef, modelDef.PrimaryKey))
.ClearLimits()
.OrderBy(""); //Invalid in Sub Selects
var subSql = expr.ToSelectStatement();
return subSql;
}
return base.GetLoadChildrenSubSelect(expr);
}
public override string SqlCurrency(string fieldOrValue, string currencySymbol) =>
SqlConcat(new[] { "'" + currencySymbol + "'", $"CONVERT(VARCHAR, CONVERT(MONEY, {fieldOrValue}), 1)" });
public override string SqlBool(bool value) => value ? "1" : "0";
public override string SqlLimit(int? offset = null, int? rows = null) => rows == null && offset == null
? ""
: rows != null
? "OFFSET " + offset.GetValueOrDefault() + " ROWS FETCH NEXT " + rows + " ROWS ONLY"
: "OFFSET " + offset.GetValueOrDefault(int.MaxValue) + " ROWS";
public override string SqlCast(object fieldOrValue, string castAs) =>
castAs == Sql.VARCHAR
? $"CAST({fieldOrValue} AS VARCHAR(MAX))"
: $"CAST({fieldOrValue} AS {castAs})";
//public override string SqlRandom => "NEWID()";
//public override void EnableForeignKeysCheck(IDbCommand cmd) => cmd.ExecNonQuery("EXEC sp_msforeachtable \"ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all\"");
//public override Task EnableForeignKeysCheckAsync(IDbCommand cmd, CancellationToken token = default) =>
// cmd.ExecNonQueryAsync("EXEC sp_msforeachtable \"ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all\"", null, token);
//public override void DisableForeignKeysCheck(IDbCommand cmd) => cmd.ExecNonQuery("EXEC sp_msforeachtable \"ALTER TABLE ? NOCHECK CONSTRAINT all\"");
//public override Task DisableForeignKeysCheckAsync(IDbCommand cmd, CancellationToken token = default) =>
// cmd.ExecNonQueryAsync("EXEC sp_msforeachtable \"ALTER TABLE ? NOCHECK CONSTRAINT all\"", null, token);
protected DbConnection Unwrap(IDbConnection db) => (DbConnection)db.ToDbConnection();
protected DbCommand Unwrap(IDbCommand cmd) => (DbCommand)cmd.ToDbCommand();
protected DbDataReader Unwrap(IDataReader reader) => (DbDataReader)reader;
#if ASYNC
public override Task OpenAsync(IDbConnection db, CancellationToken token = default)
=> Unwrap(db).OpenAsync(token);
public override Task<IDataReader> ExecuteReaderAsync(IDbCommand cmd, CancellationToken token = default)
=> Unwrap(cmd).ExecuteReaderAsync(token).Then(x => (IDataReader)x);
public override Task<int> ExecuteNonQueryAsync(IDbCommand cmd, CancellationToken token = default)
=> Unwrap(cmd).ExecuteNonQueryAsync(token);
public override Task<object> ExecuteScalarAsync(IDbCommand cmd, CancellationToken token = default)
=> Unwrap(cmd).ExecuteScalarAsync(token);
public override Task<bool> ReadAsync(IDataReader reader, CancellationToken token = default)
=> Unwrap(reader).ReadAsync(token);
public override async Task<List<T>> ReaderEach<T>(IDataReader reader, Func<T> fn, CancellationToken token = default)
{
try
{
var to = new List<T>();
while (await ReadAsync(reader, token).ConfigureAwait(false))
{
var row = fn();
to.Add(row);
}
return to;
}
finally
{
reader.Dispose();
}
}
public override async Task<Return> ReaderEach<Return>(IDataReader reader, Action fn, Return source, CancellationToken token = default)
{
try
{
while (await ReadAsync(reader, token).ConfigureAwait(false))
{
fn();
}
return source;
}
finally
{
reader.Dispose();
}
}
public override async Task<T> ReaderRead<T>(IDataReader reader, Func<T> fn, CancellationToken token = default)
{
try
{
if (await ReadAsync(reader, token).ConfigureAwait(false))
return fn();
return default(T);
}
finally
{
reader.Dispose();
}
}
#endif
//public override void InitConnection(IDbConnection dbConn)
//{
// if (dbConn is OrmLiteConnection ormLiteConn && dbConn.ToDbConnection() is SqlConnection sqlConn)
// ormLiteConn.ConnectionId = sqlConn.ClientConnectionId;
// foreach (var command in ConnectionCommands)
// {
// using var cmd = dbConn.CreateCommand();
// cmd.ExecNonQuery(command);
// }
// OnOpenConnection?.Invoke(dbConn);
//}
}
public enum BulkInsertMode
{
Optimized,
Csv,
Sql,
}
public class BulkInsertConfig
{
public int BatchSize { get; set; } = 1000;
public BulkInsertMode Mode { get; set; } = BulkInsertMode.Csv;
public ICollection<string>? InsertFields { get; set; } = null;
}
//public static class OrmLiteConfigExtensions
//{
// private static Dictionary<Type, ModelDefinition> typeModelDefinitionMap = new Dictionary<Type, ModelDefinition>();
// internal static bool CheckForIdField(IEnumerable<PropertyInfo> objProperties)
// {
// // Not using Linq.Where() and manually iterating through objProperties just to avoid dependencies on System.Xml??
// foreach (var objProperty in objProperties)
// {
// if (objProperty.Name != OrmLiteConfig.IdField) continue;
// return true;
// }
// return false;
// }
// internal static ModelDefinition GetModelDefinition(this Type modelType)
// {
// if (typeModelDefinitionMap.TryGetValue(modelType, out var modelDef))
// return modelDef;
// if (modelType.IsValueType || modelType == typeof(string))
// return null;
// var modelAliasAttr = modelType.FirstAttribute<AliasAttribute>();
// var schemaAttr = modelType.FirstAttribute<SchemaAttribute>();
// var preCreates = modelType.AllAttributes<PreCreateTableAttribute>();
// var postCreates = modelType.AllAttributes<PostCreateTableAttribute>();
// var preDrops = modelType.AllAttributes<PreDropTableAttribute>();
// var postDrops = modelType.AllAttributes<PostDropTableAttribute>();
// string JoinSql(List<string> statements)
// {
// if (statements.Count == 0)
// return null;
// var sb = StringBuilderCache.Allocate();
// foreach (var sql in statements)
// {
// if (sb.Length > 0)
// sb.AppendLine(";");
// sb.Append(sql);
// }
// var to = StringBuilderCache.ReturnAndFree(sb);
// return to;
// }
// modelDef = new ModelDefinition
// {
// ModelType = modelType,
// Name = modelType.Name,
// Alias = modelAliasAttr?.Name,
// Schema = schemaAttr?.Name,
// PreCreateTableSql = JoinSql(preCreates.Map(x => x.Sql)),
// PostCreateTableSql = JoinSql(postCreates.Map(x => x.Sql)),
// PreDropTableSql = JoinSql(preDrops.Map(x => x.Sql)),
// PostDropTableSql = JoinSql(postDrops.Map(x => x.Sql)),
// };
// modelDef.CompositeIndexes.AddRange(
// modelType.AllAttributes<CompositeIndexAttribute>().ToList());
// modelDef.UniqueConstraints.AddRange(
// modelType.AllAttributes<UniqueConstraintAttribute>().ToList());
// var objProperties = modelType.GetProperties(
// BindingFlags.Public | BindingFlags.Instance).ToList();
// var hasPkAttr = objProperties.Any(p => p.HasAttributeCached<PrimaryKeyAttribute>());
// var hasIdField = CheckForIdField(objProperties);
// var i = 0;
// var propertyInfoIdx = 0;
// foreach (var propertyInfo in objProperties)
// {
// if (propertyInfo.GetIndexParameters().Length > 0)
// continue; //Is Indexer
// var sequenceAttr = propertyInfo.FirstAttribute<SequenceAttribute>();
// var computeAttr = propertyInfo.FirstAttribute<ComputeAttribute>();
// var computedAttr = propertyInfo.FirstAttribute<ComputedAttribute>();
// var persistedAttr = propertyInfo.FirstAttribute<PersistedAttribute>();
// var customSelectAttr = propertyInfo.FirstAttribute<CustomSelectAttribute>();
// var decimalAttribute = propertyInfo.FirstAttribute<DecimalLengthAttribute>();
// var belongToAttribute = propertyInfo.FirstAttribute<BelongToAttribute>();
// var referenceAttr = propertyInfo.FirstAttribute<ReferenceAttribute>();
// var referenceFieldAttr = propertyInfo.FirstAttribute<ReferenceFieldAttribute>();
// var isRowVersion = propertyInfo.Name == ModelDefinition.RowVersionName
// && (propertyInfo.PropertyType == typeof(ulong) || propertyInfo.PropertyType == typeof(byte[]));
// var isNullableType = propertyInfo.PropertyType.IsNullableType();
// var isNullable = (!propertyInfo.PropertyType.IsValueType
// && !propertyInfo.HasAttributeNamed(nameof(RequiredAttribute)))
// || isNullableType;
// var propertyType = isNullableType
// ? Nullable.GetUnderlyingType(propertyInfo.PropertyType)
// : propertyInfo.PropertyType;
// Type treatAsType = null;
// if (propertyType.IsEnum)
// {
// var enumKind = Converters.EnumConverter.GetEnumKind(propertyType);
// if (enumKind == EnumKind.Int)
// treatAsType = Enum.GetUnderlyingType(propertyType);
// else if (enumKind == EnumKind.Char)
// treatAsType = typeof(char);
// }
// var isReference = referenceAttr != null || referenceFieldAttr != null;
// var isIgnored = propertyInfo.HasAttributeCached<IgnoreAttribute>() || isReference || computedAttr != null;
// var isFirst = !isIgnored && i++ == 0;
// var isAutoId = propertyInfo.HasAttributeCached<AutoIdAttribute>();
// var isPrimaryKey = (!hasPkAttr && (propertyInfo.Name == OrmLiteConfig.IdField || (!hasIdField && isFirst)))
// || propertyInfo.HasAttributeNamed(nameof(PrimaryKeyAttribute))
// || isAutoId;
// var isAutoIncrement = isPrimaryKey && propertyInfo.HasAttributeCached<AutoIncrementAttribute>();
// if (isAutoIncrement && propertyInfo.PropertyType == typeof(Guid))
// throw new NotSupportedException($"[AutoIncrement] is only valid for integer properties for {modelType.Name}.{propertyInfo.Name} Guid property use [AutoId] instead");
// if (isAutoId && (propertyInfo.PropertyType == typeof(int) || propertyInfo.PropertyType == typeof(long)))
// throw new NotSupportedException($"[AutoId] is only valid for Guid properties for {modelType.Name}.{propertyInfo.Name} integer property use [AutoIncrement] instead");
// var aliasAttr = propertyInfo.FirstAttribute<AliasAttribute>();
// var indexAttr = propertyInfo.FirstAttribute<IndexAttribute>();
// var isIndex = indexAttr != null;
// var isUnique = isIndex && indexAttr.Unique;
// var stringLengthAttr = propertyInfo.CalculateStringLength(decimalAttribute);
// var defaultValueAttr = propertyInfo.FirstAttribute<DefaultAttribute>();
// var referencesAttr = propertyInfo.FirstAttribute<ReferencesAttribute>();
// var fkAttr = propertyInfo.FirstAttribute<ForeignKeyAttribute>();
// var customFieldAttr = propertyInfo.FirstAttribute<CustomFieldAttribute>();
// var chkConstraintAttr = propertyInfo.FirstAttribute<CheckConstraintAttribute>();
// var order = propertyInfoIdx++;
// if (customFieldAttr != null) order = customFieldAttr.Order;
// var fieldDefinition = new FieldDefinition
// {
// ModelDef = modelDef,
// Name = propertyInfo.Name,
// Alias = aliasAttr?.Name,
// FieldType = propertyType,
// FieldTypeDefaultValue = isNullable ? null : propertyType.GetDefaultValue(),
// TreatAsType = treatAsType,
// PropertyInfo = propertyInfo,
// IsNullable = isNullable,
// IsPrimaryKey = isPrimaryKey,
// AutoIncrement = isPrimaryKey && isAutoIncrement,
// AutoId = isAutoId,
// IsIndexed = !isPrimaryKey && isIndex,
// IsUniqueIndex = isUnique,
// IsClustered = indexAttr?.Clustered == true,
// IsNonClustered = indexAttr?.NonClustered == true,
// IndexName = indexAttr?.Name,
// IsRowVersion = isRowVersion,
// IgnoreOnInsert = propertyInfo.HasAttributeCached<IgnoreOnInsertAttribute>(),
// IgnoreOnUpdate = propertyInfo.HasAttributeCached<IgnoreOnUpdateAttribute>(),
// ReturnOnInsert = propertyInfo.HasAttributeCached<ReturnOnInsertAttribute>(),
// FieldLength = stringLengthAttr?.MaximumLength,
// DefaultValue = defaultValueAttr?.DefaultValue,
// CheckConstraint = chkConstraintAttr?.Constraint,
// IsUniqueConstraint = propertyInfo.HasAttributeCached<UniqueAttribute>(),
// ForeignKey = fkAttr == null
// ? referencesAttr != null ? new ForeignKeyConstraint(referencesAttr.Type) : null
// : new ForeignKeyConstraint(fkAttr.Type, fkAttr.OnDelete, fkAttr.OnUpdate, fkAttr.ForeignKeyName),
// IsReference = isReference,
// GetValueFn = propertyInfo.CreateGetter(),
// SetValueFn = propertyInfo.CreateSetter(),
// Sequence = sequenceAttr?.Name,
// IsComputed = computeAttr != null || computedAttr != null || customSelectAttr != null,
// IsPersisted = persistedAttr != null,
// ComputeExpression = computeAttr != null ? computeAttr.Expression : string.Empty,
// CustomSelect = customSelectAttr?.Sql,
// CustomInsert = propertyInfo.FirstAttribute<CustomInsertAttribute>()?.Sql,
// CustomUpdate = propertyInfo.FirstAttribute<CustomUpdateAttribute>()?.Sql,
// Scale = decimalAttribute?.Scale,
// BelongToModelName = belongToAttribute?.BelongToTableType.GetModelDefinition().ModelName,
// CustomFieldDefinition = customFieldAttr?.Sql,
// IsRefType = propertyType.IsRefType(),
// Order = order
// };
// if (referenceFieldAttr != null)
// {
// fieldDefinition.FieldReference = new FieldReference(fieldDefinition)
// {
// RefModel = referenceFieldAttr.Model,
// RefId = referenceFieldAttr.Id,
// RefField = referenceFieldAttr.Field ?? propertyInfo.Name,
// };
// }
// if (isIgnored)
// modelDef.IgnoredFieldDefinitions.Add(fieldDefinition);
// else
// modelDef.FieldDefinitions.Add(fieldDefinition);
// if (isRowVersion)
// modelDef.RowVersion = fieldDefinition;
// }
// modelDef.AfterInit();
// Dictionary<Type, ModelDefinition> snapshot, newCache;
// do
// {
// snapshot = typeModelDefinitionMap;
// newCache = new Dictionary<Type, ModelDefinition>(typeModelDefinitionMap) { [modelType] = modelDef };
// } while (!ReferenceEquals(
// Interlocked.CompareExchange(ref typeModelDefinitionMap, newCache, snapshot), snapshot));
// LicenseUtils.AssertValidUsage(LicenseFeature.OrmLite, QuotaType.Tables, typeModelDefinitionMap.Count);
// return modelDef;
// }
//}
/// <summary>
/// Compute attribute.
/// Use to indicate that a property is a Calculated Field.
/// Use [Persisted] attribute to persist column
/// </summary>
[AttributeUsage(AttributeTargets.Property)]
public class ComputeAttribute : AttributeBase
{
public string Expression { get; set; }
public ComputeAttribute() : this(string.Empty) { }
public ComputeAttribute(string expression)
{
Expression = expression;
}
}
/// <summary>
/// Ignore calculated C# Property from being persisted in RDBMS Table
/// </summary>
[AttributeUsage(AttributeTargets.Property)]
public class ComputedAttribute : AttributeBase { }
/// <summary>
/// Whether to persist calculated column
/// </summary>
[AttributeUsage(AttributeTargets.Property)]
public class PersistedAttribute : AttributeBase { }
/// <summary>
/// Populate with a field from a foreign table in AutoQuery and Load* APIs
/// </summary>
[AttributeUsage(AttributeTargets.Property)]
public class ReferenceFieldAttribute : AttributeBase
{
/// <summary>
/// Foreign Key Table name
/// </summary>
public Type Model { get; set; }
/// <summary>
/// The Field name on current Model to use for the Foreign Key Table Lookup
/// </summary>
public string Id { get; set; }
/// <summary>
/// Specify Field to reference (if different from property name)
/// </summary>
public string Field { get; set; }
public ReferenceFieldAttribute() { }
public ReferenceFieldAttribute(Type model, string id)
{
Model = model;
Id = id;
}
public ReferenceFieldAttribute(Type model, string id, string field)
{
Model = model;
Id = id;
Field = field;
}
}
}