sqlsugar/Src/Asp.Net/SqlSugar/Abstract/EntityMaintenance/EntityMaintenance.cs

483 lines
23 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using SqlSugar.DbConvert;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Xml.Linq;
namespace SqlSugar
{
public class EntityMaintenance
{
public SqlSugarProvider Context { get; set; }
public EntityInfo GetEntityInfo<T>()
{
return GetEntityInfo(typeof(T));
}
public EntityInfo GetEntityInfoWithAttr(Type type)
{
return GetEntityInfo(type);
}
public EntityInfo GetEntityInfo(Type type)
{
var attr = type?.GetCustomAttribute<TenantAttribute>();
if (attr == null)
{
return _GetEntityInfo(type);
}
else if (attr.configId.ObjToString() == this.Context?.CurrentConnectionConfig?.ConfigId + "")
{
return _GetEntityInfo(type);
}
else if (this.Context.Root == null)
{
return _GetEntityInfo(type);
}
else if (!this.Context.Root.IsAnyConnection(attr.configId))
{
return _GetEntityInfo(type);
}
else
{
return this.Context.Root.GetConnection(attr.configId).EntityMaintenance._GetEntityInfo(type);
}
}
private EntityInfo _GetEntityInfo(Type type)
{
string cacheKey = "GetEntityInfo" + type.GetHashCode() + type.FullName + this.Context?.CurrentConnectionConfig?.ConfigId;
return this.Context.Utilities.GetReflectionInoCacheInstance().GetOrCreate(cacheKey,
() =>
{
return GetEntityInfoNoCache(type);
});
}
public EntityInfo GetEntityInfoNoCache(Type type)
{
EntityInfo result = new EntityInfo();
var sugarAttributeInfo = type.GetTypeInfo().GetCustomAttributes(typeof(SugarTable), false).Where(it => it is SugarTable).SingleOrDefault();
if (sugarAttributeInfo.HasValue())
{
var sugarTable = (SugarTable)sugarAttributeInfo;
result.DbTableName = sugarTable.TableName;
result.TableDescription = sugarTable.TableDescription.ToSqlFilter();
result.IsDisabledUpdateAll = sugarTable.IsDisabledUpdateAll;
result.IsDisabledDelete = sugarTable.IsDisabledDelete;
result.IsCreateTableFiledSort = sugarTable.IsCreateTableFiledSort;
result.Discrimator = sugarTable.Discrimator;
}
var indexs = type.GetCustomAttributes(typeof(SugarIndexAttribute));
if (indexs != null && indexs.Any())
{
result.Indexs = indexs.Select(it => it as SugarIndexAttribute).ToList();
}
if (result.TableDescription.IsNullOrEmpty()) result.TableDescription = GetTableAnnotation(type);
if (this.Context.CurrentConnectionConfig.ConfigureExternalServices != null && this.Context.CurrentConnectionConfig.ConfigureExternalServices.EntityNameService != null)
{
if (result.DbTableName == null)
{
result.DbTableName = type.Name;
}
this.Context.CurrentConnectionConfig.ConfigureExternalServices.EntityNameService(type, result);
}
result.Type = type;
result.EntityName = result.Type.Name;
result.Columns = new List<EntityColumnInfo>();
SetColumns(result);
return result;
}
public string GetTableName<T>()
{
return GetTableName(typeof(T));
}
public string GetTableName(Type entityType)
{
var typeName = entityType.Name;
if (this.Context.MappingTables == null || this.Context.MappingTables.Count == 0 || !this.Context.MappingTables.Any(it => it.EntityName == typeName))
{
var entity = this.GetEntityInfo(entityType);
if (entity.DbTableName.HasValue()) return entity.DbTableName;
else return entity.EntityName;
}
else
{
var mappingInfo = this.Context.MappingTables.SingleOrDefault(it => it.EntityName == typeName);
return mappingInfo == null ? typeName : mappingInfo.DbTableName;
}
}
public string GetTableName(string entityName)
{
var typeName = entityName;
if (this.Context.MappingTables == null || this.Context.MappingTables.Count == 0) return typeName;
else
{
var mappingInfo = this.Context.MappingTables.SingleOrDefault(it => it.EntityName == typeName);
return mappingInfo == null ? typeName : mappingInfo.DbTableName;
}
}
public string GetEntityName(string tableName)
{
if (this.Context.MappingTables == null || this.Context.MappingTables.Count == 0) return tableName;
else
{
var mappingInfo = this.Context.MappingTables.SingleOrDefault(it => it.DbTableName == tableName);
return mappingInfo == null ? tableName : mappingInfo.EntityName;
}
}
public string GetEntityName<T>()
{
return this.Context.EntityMaintenance.GetEntityInfo<T>().EntityName;
}
public string GetEntityName(Type type)
{
return this.Context.EntityMaintenance.GetEntityInfo(type).EntityName;
}
public string GetDbColumnName<T>(string propertyName)
{
return GetDbColumnName(propertyName, typeof(T));
}
public string GetDbColumnName(string propertyName, Type entityType)
{
var isAny = this.GetEntityInfo(entityType).Columns.Any(it => it.PropertyName.Equals(propertyName, StringComparison.CurrentCultureIgnoreCase));
Check.Exception(!isAny, "Property " + propertyName + " is Invalid");
var typeName = entityType.Name;
if (this.Context.MappingColumns == null || this.Context.MappingColumns.Count == 0 || !this.Context.MappingColumns.Any(it => it.EntityName == typeName && it.PropertyName == propertyName))
{
var column = this.GetEntityInfo(entityType).Columns.First(it => it.PropertyName.Equals(propertyName, StringComparison.CurrentCultureIgnoreCase));
if (column.DbColumnName.HasValue()) return column.DbColumnName;
else return column.PropertyName;
}
else
{
var mappingInfo = this.Context.MappingColumns.SingleOrDefault(it => it.EntityName == typeName && it.PropertyName == propertyName);
return mappingInfo == null ? propertyName : mappingInfo.DbColumnName;
}
}
public string GetPropertyName<T>(string dbColumnName)
{
var columnInfo=this.Context.EntityMaintenance.GetEntityInfo<T>().Columns.FirstOrDefault(it=>it.DbColumnName.EqualCase(dbColumnName));
if (columnInfo != null)
{
return columnInfo.PropertyName;
}
var typeName = typeof(T).Name;
if (this.Context.MappingColumns == null || this.Context.MappingColumns.Count == 0) return dbColumnName;
else
{
var mappingInfo = this.Context.MappingColumns.SingleOrDefault(it => it.EntityName == typeName && it.DbColumnName.Equals(dbColumnName, StringComparison.CurrentCultureIgnoreCase));
return mappingInfo == null ? dbColumnName : mappingInfo.PropertyName;
}
}
public string GetPropertyName(string dbColumnName, Type entityType)
{
var columnInfo = this.Context.EntityMaintenance.GetEntityInfo(entityType).Columns.FirstOrDefault(it => it.DbColumnName.EqualCase(dbColumnName));
if (columnInfo != null)
{
return columnInfo.PropertyName;
}
var typeName = entityType.Name;
if (this.Context.MappingColumns == null || this.Context.MappingColumns.Count == 0) return dbColumnName;
else
{
var mappingInfo = this.Context.MappingColumns.SingleOrDefault(it => it.EntityName == typeName && it.DbColumnName.Equals(dbColumnName, StringComparison.CurrentCultureIgnoreCase));
return mappingInfo == null ? dbColumnName : mappingInfo.PropertyName;
}
}
public PropertyInfo GetProperty<T>(string dbColumnName)
{
var propertyName = GetPropertyName<T>(dbColumnName);
return typeof(T).GetProperties().First(it => it.Name == propertyName);
}
/// <summary>
/// Gets the text contents of this XML element node
/// </summary>
/// <param name="entityType">entity type</param>
/// <param name="nodeAttributeName">The value of the name attribute of the XML node</param>
/// <returns>the text contents of this XML element node</returns>
public string GetXElementNodeValue(Type entityType, string nodeAttributeName)
{
try
{
if (this.Context.CurrentConnectionConfig?.MoreSettings?.IsNoReadXmlDescription == true)
{
return "";
}
if (entityType.Assembly.IsDynamic&& entityType.Assembly.FullName.StartsWith("Dynamic"))
{
return null;
}
var path = entityType.Assembly.Location;
if (string.IsNullOrEmpty(path))
{
return null;
}
FileInfo file = new FileInfo(path);
string xmlPath = entityType.Assembly.Location.Replace(file.Extension, ".xml");
if (!File.Exists(xmlPath))
{
return string.Empty;
}
XElement xe =new ReflectionInoCacheService().GetOrCreate("EntityXml_"+xmlPath,()=> XElement.Load(xmlPath));
if (xe == null)
{
return string.Empty;
}
var xeNode = xe.Element("members").Elements("member").Where(ele => ele.Attribute("name").Value == nodeAttributeName).FirstOrDefault();
if (xeNode == null)
{
return string.Empty;
}
var summary = xeNode.Element("summary");
if (summary != null)
{
return summary.Value.ToSqlFilter().Trim();
}
else
{
var summaryValue = xeNode.Elements().Where(x => x.Name.ToString().EqualCase("summary")).Select(it => it.Value).FirstOrDefault();
if(summaryValue==null)
return string.Empty;
else
return summaryValue.ToSqlFilter().Trim()??"";
}
}
catch
{
Check.ExceptionEasy("ORM error reading entity class XML, check entity XML or disable reading XML: MoreSettings IsNoReadXmlDescription set to true (same place to set DbType)", "ORM读取实体类的XML出现错误,检查实体XML或者禁用读取XML: MoreSettings里面的IsNoReadXmlDescription设为true 设置DbType的同一个地方");
throw;
}
}
/// <summary>
/// Gets the code annotation for the database table
/// </summary>
/// <param name="entityType">entity type</param>
/// <returns>the code annotation for the database table</returns>
public string GetTableAnnotation(Type entityType)
{
if (entityType.IsClass() == false)
{
return null;
}
var result= GetXElementNodeValue(entityType, $"T:{entityType.FullName}");
if (string.IsNullOrEmpty(result))
{
return null;
}
else
{
return result;
}
}
/// <summary>
/// Gets the code annotation for the field
/// </summary>
/// <param name="entityType">entity type</param>
/// <param name="dbColumnName">column name</param>
/// <returns>the code annotation for the field</returns>
public string GetPropertyAnnotation(Type entityType, string dbColumnName)
{
if (entityType.IsClass() == false || entityType == typeof(object))
{
return null;
}
var result = GetXElementNodeValue(entityType, $"P:{entityType.FullName}.{dbColumnName}");
if (string.IsNullOrEmpty(result))
{
return GetPropertyAnnotation(entityType.BaseType, dbColumnName);
}
else
{
return result;
}
}
#region Primary key
private void SetColumns(EntityInfo result)
{
foreach (var property in result.Type.GetProperties())
{
EntityColumnInfo column = new EntityColumnInfo();
//var isVirtual = property.GetGetMethod().IsVirtual;
//if (isVirtual) continue;
var navigat=property.GetCustomAttribute(typeof(Navigate));
if (navigat != null)
{
column.IsIgnore = true;
column.Navigat = navigat as Navigate;
}
var sugarColumn = property.GetCustomAttributes(typeof(SugarColumn), true)
.Where(it => it is SugarColumn)
.Select(it => (SugarColumn)it)
.FirstOrDefault();
column.ExtendedAttribute = sugarColumn?.ExtendedAttribute;
column.DbTableName = result.DbTableName;
column.EntityName = result.EntityName;
column.PropertyName = property.Name;
column.PropertyInfo = property;
column.UnderType = UtilMethods.GetUnderType(column.PropertyInfo.PropertyType);
if (sugarColumn?.IsOwnsOne==true)
{
SetValueObjectColumns(result, property, column);
}
if (sugarColumn.IsNullOrEmpty())
{
column.DbColumnName = property.Name;
}
else
{
if (sugarColumn.IsIgnore == false)
{
column.DbColumnName = sugarColumn.ColumnName.IsNullOrEmpty() ? property.Name : sugarColumn.ColumnName;
column.IsPrimarykey = sugarColumn.IsPrimaryKey;
column.IsIdentity = sugarColumn.IsIdentity;
column.ColumnDescription = sugarColumn.ColumnDescription.ToSqlFilter();
column.IsNullable = sugarColumn.IsNullable;
column.Length = sugarColumn.Length;
column.OldDbColumnName = sugarColumn.OldColumnName;
column.DataType = sugarColumn.ColumnDataType;
column.DecimalDigits = sugarColumn.DecimalDigits;
column.OracleSequenceName = sugarColumn.OracleSequenceName;
column.IsOnlyIgnoreInsert = sugarColumn.IsOnlyIgnoreInsert;
column.IsEnableUpdateVersionValidation = sugarColumn.IsEnableUpdateVersionValidation;
column.IsTranscoding = sugarColumn.IsTranscoding;
column.SerializeDateTimeFormat = sugarColumn.SerializeDateTimeFormat;
column.IsJson = sugarColumn.IsJson;
column.NoSerialize = sugarColumn.NoSerialize;
column.DefaultValue = sugarColumn.DefaultValue;
column.IndexGroupNameList = sugarColumn.IndexGroupNameList;
column.UIndexGroupNameList = sugarColumn.UniqueGroupNameList;
column.IsOnlyIgnoreUpdate = sugarColumn.IsOnlyIgnoreUpdate;
column.IsArray = sugarColumn.IsArray;
column.IsTreeKey = sugarColumn.IsTreeKey;
column.SqlParameterDbType = sugarColumn.SqlParameterDbType;
column.SqlParameterSize = sugarColumn.SqlParameterSize;
column.CreateTableFieldSort = sugarColumn.CreateTableFieldSort;
column.InsertServerTime = sugarColumn.InsertServerTime;
column.InsertSql = sugarColumn.InsertSql;
column.UpdateServerTime= sugarColumn.UpdateServerTime;
column.UpdateSql= sugarColumn.UpdateSql;
column.IsDisabledAlterColumn = sugarColumn.IsDisabledAlterColumn;
column.QuerySql = sugarColumn.QuerySql;
if (sugarColumn.IsJson && String.IsNullOrEmpty(sugarColumn.ColumnDataType))
{
if (this.Context.CurrentConnectionConfig.DbType == DbType.PostgreSQL)
{
column.DataType = "json";
}
else if (column.Length > 0)
{
column.DataType = "varchar";
}
else
{
column.DataType = "varchar(4000)";
}
}
else if (typeof(Nvarchar2PropertyConvert).Equals(sugarColumn.SqlParameterDbType)&&column.DataType==null)
{
column.DataType = "nvarchar2";
if (column.Length == 0)
{
column.Length = 200;
}
}
if (column.IsPrimarykey && column.IsOnlyIgnoreUpdate)
{
column.IsOnlyIgnoreUpdate = false;
}
}
else
{
column.IsIgnore = true;
column.NoSerialize = sugarColumn.NoSerialize;
column.ColumnDescription = sugarColumn.ColumnDescription;
column.IsJson = sugarColumn.IsJson;
column.IsArray = sugarColumn.IsArray;
}
}
if (column.ColumnDescription.IsNullOrEmpty()) column.ColumnDescription = GetPropertyAnnotation(result.Type, column.PropertyName);
if (this.Context.MappingColumns.HasValue())
{
var golbalMappingInfo = this.Context.MappingColumns.FirstOrDefault(it => it.EntityName.Equals(result.EntityName, StringComparison.CurrentCultureIgnoreCase) && it.PropertyName == column.PropertyName);
if (golbalMappingInfo != null)
column.DbColumnName = golbalMappingInfo.DbColumnName;
}
if (this.Context.IgnoreColumns.HasValue())
{
var golbalMappingInfo = this.Context.IgnoreColumns.FirstOrDefault(it => it.EntityName.Equals(result.EntityName, StringComparison.CurrentCultureIgnoreCase) && it.PropertyName == column.PropertyName);
if (golbalMappingInfo != null)
column.IsIgnore = true;
}
if (this.Context.CurrentConnectionConfig.ConfigureExternalServices != null && this.Context.CurrentConnectionConfig.ConfigureExternalServices.EntityService != null)
{
if (!column.EntityName.ObjToString().StartsWith("<>f__AnonymousType")
&&column.PropertyInfo?.ReflectedType!=typeof(DbTableInfo))
{
var isOldOwnsOne = column.IsOwnsOne;
this.Context.CurrentConnectionConfig.ConfigureExternalServices.EntityService(property, column);
if (column.IsOwnsOne == true && isOldOwnsOne == false)
{
SetValueObjectColumns(result, property, column);
continue;
}
}
}
if (column.PropertyInfo.DeclaringType != null
&& column.PropertyInfo.DeclaringType != result.Type
&&result.Columns.Any(x=>x.PropertyName==column.PropertyName))
{
continue;
}
if (column.DataType == null&& property != null&& property.PropertyType.Name.IsIn("TimeOnly"))
{
column.DataType = "time";
}
if (column.DataType == null && property != null && property.PropertyType.Name.IsIn("DateOnly"))
{
column.DataType = "date";
}
if (column.DataType == null&&column.UnderType == typeof(TimeSpan) )
{
column.DataType = "time";
column.Length = 0;
column.DecimalDigits = 0;
}
if (column.OracleSequenceName.HasValue() &&
this.Context.CurrentConnectionConfig?.MoreSettings?.EnableOracleIdentity == true)
{
column.OracleSequenceName = null;
}
result.Columns.Add(column);
}
}
private void SetValueObjectColumns(EntityInfo result, PropertyInfo property, EntityColumnInfo column)
{
column.IsIgnore = true;
column.IsOwnsOne = true;
Check.ExceptionEasy(property.PropertyType.IsClass() == false, column.PropertyName + " IsOwnsOne必须用在类上面", column.PropertyName + "IsOwnsOne must be used on the class");
Check.ExceptionEasy(property.PropertyType.FullName.IsCollectionsList() == true, column.PropertyName + " IsOwnsOne必须用在类上面", column.PropertyName + "IsOwnsOne must be used on the class");
var ownsOne = this.GetEntityInfoNoCache(property.PropertyType);
foreach (var item in ownsOne.Columns)
{
if (result.Columns.Any(it => it.PropertyName.EqualCase(item.PropertyName) || it.DbColumnName.EqualCase(item.DbColumnName)))
{
Check.ExceptionEasy($" {result.EntityName} "+ item.PropertyName+ " 存在重复定义 (IsOwnsOne) ", $" {result.EntityName} " + item.PropertyName + " Duplicate definition exists (IsOwnsOne)");
}
item.ForOwnsOnePropertyInfo = column.PropertyInfo;
result.Columns.Add(item);
}
}
#endregion
}
}