mirror of
https://gitee.com/dotnetchina/OpenAuth.Net.git
synced 2025-04-29 10:49:38 +08:00
838 lines
30 KiB
C#
838 lines
30 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Concurrent;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Linq;
|
|
using System.Text.RegularExpressions;
|
|
using CodeSmith.Engine;
|
|
using SchemaExplorer;
|
|
|
|
namespace SchemaMapper
|
|
{
|
|
public enum TableNaming
|
|
{
|
|
Mixed = 0,
|
|
Plural = 1,
|
|
Singular = 2
|
|
}
|
|
|
|
public enum EntityNaming
|
|
{
|
|
Preserve = 0,
|
|
Plural = 1,
|
|
Singular = 2
|
|
}
|
|
|
|
public enum RelationshipNaming
|
|
{
|
|
None = 0,
|
|
Plural = 1,
|
|
ListSuffix = 2
|
|
}
|
|
|
|
public enum ContextNaming
|
|
{
|
|
Preserve = 0,
|
|
Plural = 1,
|
|
TableSuffix = 2
|
|
}
|
|
|
|
public class GeneratorSettings
|
|
{
|
|
public GeneratorSettings()
|
|
{
|
|
RelationshipNaming = RelationshipNaming.ListSuffix;
|
|
EntityNaming = EntityNaming.Singular;
|
|
TableNaming = TableNaming.Singular;
|
|
CleanExpressions = new List<string> { @"^\d+" };
|
|
IgnoreExpressions = new List<string>();
|
|
}
|
|
|
|
public TableNaming TableNaming { get; set; }
|
|
|
|
public EntityNaming EntityNaming { get; set; }
|
|
|
|
public RelationshipNaming RelationshipNaming { get; set; }
|
|
|
|
public ContextNaming ContextNaming { get; set; }
|
|
|
|
public List<string> IgnoreExpressions { get; set; }
|
|
|
|
public List<string> CleanExpressions { get; set; }
|
|
|
|
public bool InclusionMode { get; set; }
|
|
|
|
public bool IsIgnored(string name)
|
|
{
|
|
if (IgnoreExpressions.Count == 0)
|
|
return false;
|
|
|
|
bool isMatch = IgnoreExpressions.Any(regex => Regex.IsMatch(name, regex));
|
|
|
|
return InclusionMode ? !isMatch : isMatch;
|
|
}
|
|
|
|
public string CleanName(string name)
|
|
{
|
|
if (CleanExpressions.Count == 0)
|
|
return name;
|
|
|
|
foreach (var regex in CleanExpressions.Where(r => !string.IsNullOrEmpty(r)))
|
|
if (Regex.IsMatch(name, regex))
|
|
return Regex.Replace(name, regex, "");
|
|
|
|
return name;
|
|
}
|
|
|
|
public string RelationshipName(string name)
|
|
{
|
|
if (RelationshipNaming == RelationshipNaming.None)
|
|
return name;
|
|
|
|
if (RelationshipNaming == RelationshipNaming.ListSuffix)
|
|
return name + "List";
|
|
|
|
return StringUtil.ToPascalCase(StringUtil.ToPlural(name));
|
|
}
|
|
|
|
public string ContextName(string name)
|
|
{
|
|
if (ContextNaming == ContextNaming.Preserve)
|
|
return name;
|
|
|
|
if (ContextNaming == ContextNaming.TableSuffix)
|
|
return name + "Table";
|
|
|
|
return StringUtil.ToPascalCase(StringUtil.ToPlural(name));
|
|
}
|
|
|
|
public string EntityName(string name)
|
|
{
|
|
if (TableNaming != TableNaming.Plural && EntityNaming == EntityNaming.Plural)
|
|
name = StringUtil.ToPlural(name);
|
|
else if (TableNaming != TableNaming.Singular && EntityNaming == EntityNaming.Singular)
|
|
name = StringUtil.ToSingular(name);
|
|
|
|
return StringUtil.ToPascalCase(name);
|
|
}
|
|
}
|
|
|
|
public class SchemaItemProcessedEventArgs : EventArgs
|
|
{
|
|
public SchemaItemProcessedEventArgs(string name)
|
|
{
|
|
_name = name;
|
|
}
|
|
|
|
private readonly string _name;
|
|
public string Name
|
|
{
|
|
get { return _name; }
|
|
}
|
|
}
|
|
|
|
public class UniqueNamer
|
|
{
|
|
private readonly ConcurrentDictionary<string, HashSet<string>> _names;
|
|
|
|
public UniqueNamer()
|
|
{
|
|
_names = new ConcurrentDictionary<string, HashSet<string>>(StringComparer.OrdinalIgnoreCase);
|
|
Comparer = StringComparer.CurrentCulture;
|
|
|
|
// add existing
|
|
UniqueContextName("ChangeTracker");
|
|
UniqueContextName("Configuration");
|
|
UniqueContextName("Database");
|
|
UniqueContextName("InternalContext");
|
|
}
|
|
|
|
public IEqualityComparer<string> Comparer { get; set; }
|
|
|
|
public string UniqueName(string bucketName, string name)
|
|
{
|
|
var hashSet = _names.GetOrAdd(bucketName, k => new HashSet<string>(Comparer));
|
|
string result = name.MakeUnique(hashSet.Contains);
|
|
hashSet.Add(result);
|
|
|
|
return result;
|
|
}
|
|
|
|
public string UniqueClassName(string className)
|
|
{
|
|
const string globalClassName = "global::ClassName";
|
|
return UniqueName(globalClassName, className);
|
|
}
|
|
|
|
public string UniqueContextName(string name)
|
|
{
|
|
const string globalContextname = "global::ContextName";
|
|
return UniqueName(globalContextname, name);
|
|
}
|
|
|
|
public string UniqueRelationshipName(string name)
|
|
{
|
|
const string globalContextname = "global::RelationshipName";
|
|
return UniqueName(globalContextname, name);
|
|
}
|
|
|
|
}
|
|
|
|
public class Generator
|
|
{
|
|
private readonly UniqueNamer _namer;
|
|
|
|
public Generator()
|
|
{
|
|
_settings = new GeneratorSettings();
|
|
_namer = new UniqueNamer();
|
|
}
|
|
|
|
public event EventHandler<SchemaItemProcessedEventArgs> SchemaItemProcessed;
|
|
protected void OnSchemaItemProcessed(string name)
|
|
{
|
|
var handler = SchemaItemProcessed;
|
|
if (handler == null)
|
|
return;
|
|
|
|
handler(this, new SchemaItemProcessedEventArgs(name));
|
|
}
|
|
|
|
private readonly GeneratorSettings _settings;
|
|
public GeneratorSettings Settings
|
|
{
|
|
get { return _settings; }
|
|
}
|
|
|
|
//按表信息创建DbContext
|
|
public EntityContext Generate(TableSchema tableSchema)
|
|
{
|
|
// only DeepLoad when in ignore mode
|
|
tableSchema.DeepLoad = !Settings.InclusionMode;
|
|
|
|
var entityContext = new EntityContext();
|
|
entityContext.DatabaseName = tableSchema.Database.Name;
|
|
|
|
string dataContextName = StringUtil.ToPascalCase(tableSchema.Database.Name) + "Context";
|
|
dataContextName = _namer.UniqueClassName(dataContextName);
|
|
|
|
entityContext.ClassName = dataContextName;
|
|
|
|
GetEntity(entityContext, tableSchema);
|
|
|
|
|
|
return entityContext;
|
|
}
|
|
|
|
//按数据库连接信息创建DbContext
|
|
public EntityContext Generate(DatabaseSchema databaseSchema)
|
|
{
|
|
// only DeepLoad when in ignore mode
|
|
databaseSchema.DeepLoad = !Settings.InclusionMode;
|
|
|
|
var entityContext = new EntityContext();
|
|
entityContext.DatabaseName = databaseSchema.Name;
|
|
|
|
string dataContextName = StringUtil.ToPascalCase(databaseSchema.Name) + "Context";
|
|
dataContextName = _namer.UniqueClassName(dataContextName);
|
|
|
|
entityContext.ClassName = dataContextName;
|
|
|
|
foreach (TableSchema t in databaseSchema.Tables)
|
|
{
|
|
if (Settings.IsIgnored(t.FullName))
|
|
{
|
|
Debug.WriteLine("Skipping Table: " + t.FullName);
|
|
}
|
|
else if (IsManyToMany(t))
|
|
{
|
|
CreateManyToMany(entityContext, t);
|
|
}
|
|
else
|
|
{
|
|
Debug.WriteLine("Getting Table Schema: " + t.FullName);
|
|
GetEntity(entityContext, t);
|
|
}
|
|
|
|
OnSchemaItemProcessed(t.FullName);
|
|
}
|
|
|
|
return entityContext;
|
|
}
|
|
|
|
//根据DbContext和tableSchema获取实体
|
|
public Entity GetEntity(EntityContext entityContext, TableSchema tableSchema, bool processRelationships = true, bool processMethods = true)
|
|
{
|
|
string key = tableSchema.FullName;
|
|
|
|
Entity entity = entityContext.Entities.ByTable(key)
|
|
?? CreateEntity(entityContext, tableSchema);
|
|
|
|
if (!entity.Properties.IsProcessed)
|
|
CreateProperties(entity, tableSchema);
|
|
|
|
if (processRelationships && !entity.Relationships.IsProcessed)
|
|
CreateRelationships(entityContext, entity, tableSchema);
|
|
|
|
if (processMethods && !entity.Methods.IsProcessed)
|
|
CreateMethods(entity, tableSchema);
|
|
|
|
entity.IsProcessed = true;
|
|
return entity;
|
|
}
|
|
|
|
private Entity CreateEntity(EntityContext entityContext, TableSchema tableSchema)
|
|
{
|
|
var entity = new Entity
|
|
{
|
|
FullName = tableSchema.FullName,
|
|
TableName = tableSchema.Name,
|
|
TableSchema = tableSchema.Owner,
|
|
Description = tableSchema.Description
|
|
};
|
|
|
|
string className = ToClassName(tableSchema.Name);
|
|
className = _namer.UniqueClassName(className);
|
|
|
|
string mappingName = className + "Map";
|
|
mappingName = _namer.UniqueClassName(mappingName);
|
|
|
|
string contextName = Settings.ContextName(className);
|
|
contextName = ToPropertyName(entityContext.ClassName, contextName);
|
|
contextName = _namer.UniqueContextName(contextName);
|
|
|
|
entity.ClassName = className;
|
|
entity.ContextName = contextName;
|
|
entity.MappingName = mappingName;
|
|
|
|
entityContext.Entities.Add(entity);
|
|
|
|
return entity;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 创建实体的属性
|
|
/// </summary>
|
|
private void CreateProperties(Entity entity, TableSchema tableSchema)
|
|
{
|
|
foreach (ColumnSchema columnSchema in tableSchema.Columns)
|
|
{
|
|
// skip unsupported type
|
|
if (columnSchema.NativeType.Equals("hierarchyid", StringComparison.OrdinalIgnoreCase)
|
|
|| columnSchema.NativeType.Equals("sql_variant", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
Debug.WriteLine(string.Format("Skipping column '{0}' because it has an unsupported db type '{1}'.",
|
|
columnSchema.Name, columnSchema.NativeType));
|
|
continue;
|
|
}
|
|
|
|
Property property = entity.Properties.ByColumn(columnSchema.Name);
|
|
|
|
if (property == null)
|
|
{
|
|
property = new Property { ColumnName = columnSchema.Name };
|
|
entity.Properties.Add(property);
|
|
}
|
|
|
|
string propertyName = ToPropertyName(entity.ClassName, columnSchema.Name);
|
|
propertyName = _namer.UniqueName(entity.ClassName, propertyName);
|
|
|
|
property.PropertyName = propertyName;
|
|
|
|
property.DataType = columnSchema.DataType;
|
|
property.SystemType = columnSchema.SystemType;
|
|
property.NativeType = columnSchema.NativeType;
|
|
property.Description = columnSchema.Description;
|
|
|
|
property.IsPrimaryKey = columnSchema.IsPrimaryKeyMember;
|
|
property.IsForeignKey = columnSchema.IsForeignKeyMember;
|
|
property.IsNullable = columnSchema.AllowDBNull;
|
|
|
|
property.IsIdentity = IsIdentity(columnSchema);
|
|
property.IsRowVersion = IsRowVersion(columnSchema);
|
|
property.IsAutoGenerated = IsDbGenerated(columnSchema);
|
|
|
|
if (columnSchema.IsUnique)
|
|
property.IsUnique = columnSchema.IsUnique;
|
|
|
|
if (property.SystemType == typeof(string)
|
|
|| property.SystemType == typeof(byte[]))
|
|
{
|
|
property.MaxLength = columnSchema.Size;
|
|
}
|
|
|
|
if (property.SystemType == typeof(float)
|
|
|| property.SystemType == typeof(double)
|
|
|| property.SystemType == typeof(decimal))
|
|
{
|
|
property.Precision = columnSchema.Precision;
|
|
property.Scale = columnSchema.Scale;
|
|
}
|
|
|
|
property.IsProcessed = true;
|
|
}
|
|
|
|
entity.Properties.IsProcessed = true;
|
|
}
|
|
|
|
|
|
private void CreateRelationships(EntityContext entityContext, Entity entity, TableSchema tableSchema)
|
|
{
|
|
foreach (TableKeySchema tableKey in tableSchema.ForeignKeys)
|
|
{
|
|
if (Settings.IsIgnored(tableKey.ForeignKeyTable.FullName)
|
|
|| Settings.IsIgnored(tableKey.PrimaryKeyTable.FullName))
|
|
{
|
|
Debug.WriteLine("Skipping relationship '{0}' because table '{1}' or '{2}' is ignored.",
|
|
tableKey.FullName, tableKey.ForeignKeyTable.FullName, tableKey.PrimaryKeyTable.FullName);
|
|
|
|
continue;
|
|
}
|
|
|
|
CreateRelationship(entityContext, entity, tableKey);
|
|
}
|
|
|
|
entity.Relationships.IsProcessed = true;
|
|
}
|
|
|
|
private void CreateRelationship(EntityContext entityContext, Entity foreignEntity, TableKeySchema tableKeySchema)
|
|
{
|
|
Entity primaryEntity = GetEntity(entityContext, tableKeySchema.PrimaryKeyTable, false, false);
|
|
|
|
string primaryName = primaryEntity.ClassName;
|
|
string foreignName = foreignEntity.ClassName;
|
|
|
|
string relationshipName = tableKeySchema.Name;
|
|
relationshipName = _namer.UniqueRelationshipName(relationshipName);
|
|
|
|
bool isCascadeDelete = IsCascadeDelete(tableKeySchema);
|
|
bool foreignMembersRequired;
|
|
bool primaryMembersRequired;
|
|
|
|
var foreignMembers = GetKeyMembers(foreignEntity, tableKeySchema.ForeignKeyMemberColumns, tableKeySchema.Name, out foreignMembersRequired);
|
|
var primaryMembers = GetKeyMembers(primaryEntity, tableKeySchema.PrimaryKeyMemberColumns, tableKeySchema.Name, out primaryMembersRequired);
|
|
|
|
Relationship foreignRelationship = foreignEntity.Relationships
|
|
.FirstOrDefault(r => r.RelationshipName == relationshipName && r.IsForeignKey);
|
|
|
|
if (foreignRelationship == null)
|
|
{
|
|
foreignRelationship = new Relationship { RelationshipName = relationshipName };
|
|
foreignEntity.Relationships.Add(foreignRelationship);
|
|
}
|
|
foreignRelationship.IsMapped = true;
|
|
foreignRelationship.IsForeignKey = true;
|
|
foreignRelationship.ThisCardinality = foreignMembersRequired ? Cardinality.One : Cardinality.ZeroOrOne;
|
|
foreignRelationship.ThisEntity = foreignName;
|
|
foreignRelationship.ThisProperties = new List<string>(foreignMembers);
|
|
foreignRelationship.OtherEntity = primaryName;
|
|
foreignRelationship.OtherProperties = new List<string>(primaryMembers);
|
|
foreignRelationship.CascadeDelete = isCascadeDelete;
|
|
|
|
string prefix = GetMemberPrefix(foreignRelationship, primaryName, foreignName);
|
|
|
|
string foreignPropertyName = ToPropertyName(foreignEntity.ClassName, prefix + primaryName);
|
|
foreignPropertyName = _namer.UniqueName(foreignEntity.ClassName, foreignPropertyName);
|
|
foreignRelationship.ThisPropertyName = foreignPropertyName;
|
|
|
|
// add reverse
|
|
Relationship primaryRelationship = primaryEntity.Relationships
|
|
.FirstOrDefault(r => r.RelationshipName == relationshipName && r.IsForeignKey == false);
|
|
|
|
if (primaryRelationship == null)
|
|
{
|
|
primaryRelationship = new Relationship { RelationshipName = relationshipName };
|
|
primaryEntity.Relationships.Add(primaryRelationship);
|
|
}
|
|
|
|
primaryRelationship.IsMapped = false;
|
|
primaryRelationship.IsForeignKey = false;
|
|
primaryRelationship.ThisEntity = primaryName;
|
|
primaryRelationship.ThisProperties = new List<string>(primaryMembers);
|
|
primaryRelationship.OtherEntity = foreignName;
|
|
primaryRelationship.OtherProperties = new List<string>(foreignMembers);
|
|
primaryRelationship.CascadeDelete = isCascadeDelete;
|
|
|
|
bool isOneToOne = IsOneToOne(tableKeySchema, foreignRelationship);
|
|
|
|
if (isOneToOne)
|
|
primaryRelationship.ThisCardinality = primaryMembersRequired ? Cardinality.One : Cardinality.ZeroOrOne;
|
|
else
|
|
primaryRelationship.ThisCardinality = Cardinality.Many;
|
|
|
|
string primaryPropertyName = prefix + foreignName;
|
|
if (!isOneToOne)
|
|
primaryPropertyName = Settings.RelationshipName(primaryPropertyName);
|
|
|
|
primaryPropertyName = ToPropertyName(primaryEntity.ClassName, primaryPropertyName);
|
|
primaryPropertyName = _namer.UniqueName(primaryEntity.ClassName, primaryPropertyName);
|
|
|
|
primaryRelationship.ThisPropertyName = primaryPropertyName;
|
|
|
|
foreignRelationship.OtherPropertyName = primaryRelationship.ThisPropertyName;
|
|
foreignRelationship.OtherCardinality = primaryRelationship.ThisCardinality;
|
|
|
|
primaryRelationship.OtherPropertyName = foreignRelationship.ThisPropertyName;
|
|
primaryRelationship.OtherCardinality = foreignRelationship.ThisCardinality;
|
|
|
|
foreignRelationship.IsProcessed = true;
|
|
primaryRelationship.IsProcessed = true;
|
|
}
|
|
|
|
private void CreateManyToMany(EntityContext entityContext, TableSchema joinTable)
|
|
{
|
|
if (joinTable.ForeignKeys.Count != 2)
|
|
return;
|
|
|
|
var joinTableName = joinTable.Name;
|
|
var joinSchemaName = joinTable.Owner;
|
|
|
|
// first fkey is always left, second fkey is right
|
|
var leftForeignKey = joinTable.ForeignKeys[0];
|
|
var leftTable = leftForeignKey.PrimaryKeyTable;
|
|
var joinLeftColumn = leftForeignKey.ForeignKeyMemberColumns.Select(c => c.Name).ToList();
|
|
var leftEntity = GetEntity(entityContext, leftTable, false, false);
|
|
|
|
var rightForeignKey = joinTable.ForeignKeys[1];
|
|
var rightTable = rightForeignKey.PrimaryKeyTable;
|
|
var joinRightColumn = rightForeignKey.ForeignKeyMemberColumns.Select(c => c.Name).ToList();
|
|
var rightEntity = GetEntity(entityContext, rightTable, false, false);
|
|
|
|
string leftPropertyName = Settings.RelationshipName(rightEntity.ClassName);
|
|
leftPropertyName = _namer.UniqueName(leftEntity.ClassName, leftPropertyName);
|
|
|
|
string rightPropertyName = Settings.RelationshipName(leftEntity.ClassName);
|
|
rightPropertyName = _namer.UniqueName(rightEntity.ClassName, rightPropertyName);
|
|
|
|
string relationshipName = string.Format("{0}|{1}",
|
|
leftForeignKey.Name,
|
|
rightForeignKey.Name);
|
|
|
|
relationshipName = _namer.UniqueRelationshipName(relationshipName);
|
|
|
|
var left = new Relationship { RelationshipName = relationshipName };
|
|
left.IsForeignKey = false;
|
|
left.IsMapped = true;
|
|
|
|
left.ThisCardinality = Cardinality.Many;
|
|
left.ThisEntity = leftEntity.ClassName;
|
|
left.ThisPropertyName = leftPropertyName;
|
|
|
|
left.OtherCardinality = Cardinality.Many;
|
|
left.OtherEntity = rightEntity.ClassName;
|
|
left.OtherPropertyName = rightPropertyName;
|
|
|
|
left.JoinTable = joinTableName;
|
|
left.JoinSchema = joinSchemaName;
|
|
left.JoinThisColumn = new List<string>(joinLeftColumn);
|
|
left.JoinOtherColumn = new List<string>(joinRightColumn);
|
|
|
|
leftEntity.Relationships.Add(left);
|
|
|
|
var right = new Relationship { RelationshipName = relationshipName };
|
|
right.IsForeignKey = false;
|
|
right.IsMapped = false;
|
|
|
|
right.ThisCardinality = Cardinality.Many;
|
|
right.ThisEntity = rightEntity.ClassName;
|
|
right.ThisPropertyName = rightPropertyName;
|
|
|
|
right.OtherCardinality = Cardinality.Many;
|
|
right.OtherEntity = leftEntity.ClassName;
|
|
right.OtherPropertyName = leftPropertyName;
|
|
|
|
right.JoinTable = joinTableName;
|
|
right.JoinSchema = joinSchemaName;
|
|
right.JoinThisColumn = new List<string>(joinRightColumn);
|
|
right.JoinOtherColumn = new List<string>(joinLeftColumn);
|
|
|
|
rightEntity.Relationships.Add(right);
|
|
}
|
|
|
|
|
|
private void CreateMethods(Entity entity, TableSchema tableSchema)
|
|
{
|
|
if (tableSchema.HasPrimaryKey)
|
|
{
|
|
var method = GetMethodFromColumns(entity, tableSchema.PrimaryKey.MemberColumns);
|
|
if (method != null)
|
|
{
|
|
method.IsKey = true;
|
|
method.SourceName = tableSchema.PrimaryKey.FullName;
|
|
|
|
if (!entity.Methods.Any(m => m.NameSuffix == method.NameSuffix))
|
|
entity.Methods.Add(method);
|
|
}
|
|
}
|
|
|
|
GetIndexMethods(entity, tableSchema);
|
|
GetForeignKeyMethods(entity, tableSchema);
|
|
|
|
entity.Methods.IsProcessed = true;
|
|
}
|
|
|
|
private static void GetForeignKeyMethods(Entity entity, TableSchema table)
|
|
{
|
|
var columns = new List<ColumnSchema>();
|
|
|
|
foreach (ColumnSchema column in table.ForeignKeyColumns)
|
|
{
|
|
columns.Add(column);
|
|
|
|
Method method = GetMethodFromColumns(entity, columns);
|
|
if (method != null && !entity.Methods.Any(m => m.NameSuffix == method.NameSuffix))
|
|
entity.Methods.Add(method);
|
|
|
|
columns.Clear();
|
|
}
|
|
}
|
|
|
|
private static void GetIndexMethods(Entity entity, TableSchema table)
|
|
{
|
|
foreach (IndexSchema index in table.Indexes)
|
|
{
|
|
Method method = GetMethodFromColumns(entity, index.MemberColumns);
|
|
if (method == null)
|
|
continue;
|
|
|
|
method.SourceName = index.FullName;
|
|
method.IsUnique = index.IsUnique;
|
|
method.IsIndex = true;
|
|
|
|
if (!entity.Methods.Any(m => m.NameSuffix == method.NameSuffix))
|
|
entity.Methods.Add(method);
|
|
}
|
|
}
|
|
|
|
private static Method GetMethodFromColumns(Entity entity, IEnumerable<ColumnSchema> columns)
|
|
{
|
|
var method = new Method();
|
|
string methodName = string.Empty;
|
|
|
|
foreach (var column in columns)
|
|
{
|
|
var property = entity.Properties.ByColumn(column.Name);
|
|
if (property == null)
|
|
continue;
|
|
|
|
method.Properties.Add(property);
|
|
methodName += property.PropertyName;
|
|
}
|
|
|
|
if (method.Properties.Count == 0)
|
|
return null;
|
|
|
|
method.NameSuffix = methodName;
|
|
return method;
|
|
}
|
|
|
|
|
|
private static List<string> GetKeyMembers(Entity entity, IEnumerable<MemberColumnSchema> members, string name, out bool isRequired)
|
|
{
|
|
var keyMembers = new List<string>();
|
|
isRequired = false;
|
|
|
|
foreach (var member in members)
|
|
{
|
|
var property = entity.Properties.ByColumn(member.Name);
|
|
|
|
if (property == null)
|
|
throw new InvalidOperationException(string.Format(
|
|
"Could not find column {0} for relationship {1}.",
|
|
member.Name,
|
|
name));
|
|
|
|
if (!isRequired)
|
|
isRequired = property.IsRequired;
|
|
|
|
keyMembers.Add(property.PropertyName);
|
|
}
|
|
|
|
return keyMembers;
|
|
}
|
|
|
|
private static string GetMemberPrefix(Relationship relationship, string primaryClass, string foreignClass)
|
|
{
|
|
string thisKey = relationship.ThisProperties.FirstOrDefault() ?? string.Empty;
|
|
string otherKey = relationship.OtherProperties.FirstOrDefault() ?? string.Empty;
|
|
|
|
bool isSameName = thisKey.Equals(otherKey, StringComparison.OrdinalIgnoreCase);
|
|
isSameName = (isSameName || thisKey.Equals(primaryClass + otherKey, StringComparison.OrdinalIgnoreCase));
|
|
|
|
string prefix = string.Empty;
|
|
if (isSameName)
|
|
return prefix;
|
|
|
|
prefix = thisKey.Replace(otherKey, "");
|
|
prefix = prefix.Replace(primaryClass, "");
|
|
prefix = prefix.Replace(foreignClass, "");
|
|
prefix = Regex.Replace(prefix, @"(_ID|_id|_Id|\.ID|\.id|\.Id|ID|Id)$", "");
|
|
prefix = Regex.Replace(prefix, @"^\d", "");
|
|
|
|
return prefix;
|
|
}
|
|
|
|
private static bool IsOneToOne(TableKeySchema tableKeySchema, Relationship foreignRelationship)
|
|
{
|
|
bool isFkeyPkey = tableKeySchema.ForeignKeyTable.HasPrimaryKey
|
|
&& tableKeySchema.ForeignKeyTable.PrimaryKey != null
|
|
&& tableKeySchema.ForeignKeyTable.PrimaryKey.MemberColumns.Count == 1
|
|
&& tableKeySchema.ForeignKeyTable.PrimaryKey.MemberColumns.Contains(
|
|
foreignRelationship.ThisProperties.FirstOrDefault());
|
|
|
|
if (isFkeyPkey)
|
|
return true;
|
|
|
|
// if f.key is unique
|
|
return tableKeySchema.ForeignKeyMemberColumns.All(column => column.IsUnique);
|
|
}
|
|
|
|
private static bool IsManyToMany(TableSchema tableSchema)
|
|
{
|
|
// 1) Table must have Two ForeignKeys.
|
|
// 2) All columns must be either...
|
|
// a) Member of a Foreign Key.
|
|
// b) DbGenerated
|
|
|
|
if (tableSchema.Columns.Count < 2)
|
|
return false;
|
|
|
|
if (tableSchema.ForeignKeyColumns.Count != 2)
|
|
return false;
|
|
|
|
// all columns are fkeys
|
|
if (tableSchema.Columns.Count == 2 &&
|
|
tableSchema.ForeignKeyColumns.Count == 2)
|
|
return true;
|
|
|
|
// check all non fkey columns to make sure db gen'd
|
|
return tableSchema.NonForeignKeyColumns.All(c =>
|
|
IsDbGenerated(c) || HasDefaultValue(c));
|
|
}
|
|
|
|
#region Name Helpers
|
|
private string ToClassName(string name)
|
|
{
|
|
name = Settings.EntityName(name);
|
|
string legalName = ToLegalName(name);
|
|
|
|
return legalName;
|
|
}
|
|
|
|
private string ToPropertyName(string className, string name)
|
|
{
|
|
string propertyName = ToLegalName(name);
|
|
if (className.Equals(propertyName, StringComparison.OrdinalIgnoreCase))
|
|
propertyName += "Member";
|
|
|
|
return propertyName;
|
|
}
|
|
|
|
private string ToLegalName(string name)
|
|
{
|
|
string legalName = Settings.CleanName(name);
|
|
legalName = StringUtil.ToPascalCase(legalName);
|
|
|
|
return legalName;
|
|
}
|
|
#endregion
|
|
|
|
#region Column Flag Helpers
|
|
private static bool IsCascadeDelete(SchemaObjectBase column)
|
|
{
|
|
bool cascadeDelete = false;
|
|
string value;
|
|
try
|
|
{
|
|
if (column.ExtendedProperties.Contains(ExtendedPropertyNames.CascadeDelete))
|
|
{
|
|
value = column.ExtendedProperties[ExtendedPropertyNames.CascadeDelete].Value.ToString();
|
|
bool.TryParse(value, out cascadeDelete);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Debug.WriteLine("Error: " + ex.Message);
|
|
}
|
|
|
|
return cascadeDelete;
|
|
}
|
|
|
|
private static bool IsRowVersion(DataObjectBase column)
|
|
{
|
|
bool isTimeStamp = column.NativeType.Equals(
|
|
"timestamp", StringComparison.OrdinalIgnoreCase);
|
|
bool isRowVersion = column.NativeType.Equals(
|
|
"rowversion", StringComparison.OrdinalIgnoreCase);
|
|
|
|
return (isTimeStamp || isRowVersion);
|
|
}
|
|
|
|
private static bool IsDbGenerated(DataObjectBase column)
|
|
{
|
|
if (IsRowVersion(column))
|
|
return true;
|
|
|
|
if (IsIdentity(column))
|
|
return true;
|
|
|
|
bool isComputed = false;
|
|
string value;
|
|
try
|
|
{
|
|
if (column.ExtendedProperties.Contains(ExtendedPropertyNames.IsComputed))
|
|
{
|
|
value = column.ExtendedProperties[ExtendedPropertyNames.IsComputed].Value.ToString();
|
|
bool.TryParse(value, out isComputed);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Debug.WriteLine("Error: " + ex.Message);
|
|
}
|
|
|
|
return isComputed;
|
|
}
|
|
|
|
private static bool IsIdentity(DataObjectBase column)
|
|
{
|
|
string temp;
|
|
bool isIdentity = false;
|
|
try
|
|
{
|
|
if (column.ExtendedProperties.Contains(ExtendedPropertyNames.IsIdentity))
|
|
{
|
|
temp = column.ExtendedProperties[ExtendedPropertyNames.IsIdentity].Value.ToString();
|
|
bool.TryParse(temp, out isIdentity);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Debug.WriteLine("Error: " + ex.Message);
|
|
}
|
|
|
|
return isIdentity;
|
|
}
|
|
|
|
private static bool HasDefaultValue(DataObjectBase column)
|
|
{
|
|
try
|
|
{
|
|
if (!column.ExtendedProperties.Contains(ExtendedPropertyNames.DefaultValue))
|
|
return false;
|
|
|
|
string value = column.ExtendedProperties[ExtendedPropertyNames.DefaultValue].Value.ToString();
|
|
return !string.IsNullOrEmpty(value);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Debug.WriteLine("Error: " + ex.Message);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
#endregion
|
|
}
|
|
}
|