public List <String> GetTable(EntityDef r) { var DuplicatedInMySqlViewPoint = new HashSet <Key>(); var NondirectionalKeys = new HashSet <ByIndex>(); foreach (var k in (new Key[] { r.PrimaryKey }).Concat(r.UniqueKeys).Concat(r.NonUniqueKeys)) { var Index = new ByIndex { Columns = k.Columns.Select(c => c.Name).ToList() }; if (!NondirectionalKeys.Contains(Index)) { NondirectionalKeys.Add(Index); } else { DuplicatedInMySqlViewPoint.Add(k); } } var FieldsAndKeys = new List <List <String> >(); foreach (var f in r.Fields) { if (f.Attribute.OnColumn) { FieldsAndKeys.Add(GetColumnDef(f)); } } var FieldDict = r.Fields.ToDictionary(f => f.Name); { var Name = RelationSchemaExtensions.GetLimitedKeyName("PK", String.Format("{0}_{1}", r.CollectionName, r.PrimaryKey.Columns.FriendlyName()), MaxNameLength); foreach (var c in r.PrimaryKey.Columns) { var f = FieldDict[c.Name]; if (f.Type.OnOptional) { throw new InvalidOperationException(String.Format("MySQL主键中不支持NULL字段'{0}': {1}", Name, f.Name)); } } FieldsAndKeys.Add(GetPrimaryKey(r.PrimaryKey, Name)); } foreach (var k in r.UniqueKeys) { if (DuplicatedInMySqlViewPoint.Contains(k)) { continue; } var Name = RelationSchemaExtensions.GetLimitedKeyName("UQ", String.Format("{0}_{1}", r.CollectionName, k.Columns.FriendlyName()), MaxNameLength); FieldsAndKeys.Add(GetUniqueKey(k, Name)); } var Options = new List <List <String> >(); if (WithComment) { if (r.Description != "") { Options.Add(new List <String> { "COMMENT " + GetSqlStringLiteral(r.Description) }); } } var NonUniqueKeys = new List <String>(); foreach (var k in r.NonUniqueKeys) { if (DuplicatedInMySqlViewPoint.Contains(k)) { continue; } var Name = RelationSchemaExtensions.GetLimitedKeyName("IX", String.Format("{0}_{1}", r.CollectionName, k.Columns.FriendlyName()), MaxNameLength); NonUniqueKeys.AddRange(GetNonUniqueKey(k, Name, r.CollectionName)); } return(GetTemplate("Table").Substitute("Name", r.CollectionName).Substitute("FieldsAndKeys", JoinWithComma(FieldsAndKeys.ToArray())).Substitute("Options", JoinWithComma(Options.ToArray())).Substitute("NonUniqueKeys", NonUniqueKeys)); }
public static void VerifyEntityForeignKeys(this Schema s) { var Entities = s.Types.Where(t => t.OnEntity).Select(t => t.Entity).ToList(); var IndexDict = new Dictionary <String, HashSet <ByIndex> >(StringComparer.OrdinalIgnoreCase); foreach (var e in Entities) { var h = new HashSet <ByIndex>(); foreach (var k in (new Key[] { e.PrimaryKey }).Concat(e.UniqueKeys).Concat(e.NonUniqueKeys)) { for (int i = 1; i <= k.Columns.Count; i += 1) { var SubIndex = new ByIndex { Columns = k.Columns.Take(i).Select(c => c.Name).ToList() }; if (!h.Contains(SubIndex)) { h.Add(SubIndex); } } } IndexDict.Add(e.Name, h); } foreach (var e in Entities) { foreach (var a in e.Fields.Where(f => f.Attribute.OnNavigation)) { String OtherRecordName; if (a.Type.OnTypeRef) { OtherRecordName = a.Type.TypeRef.Value; } else if (a.Type.OnOptional) { OtherRecordName = a.Type.Optional.Value; } else if (a.Type.OnList) { OtherRecordName = a.Type.List.Value; } else { throw new InvalidOperationException(); } //FK和FNK只需要目标表上的键有索引,RFK和RFNK需要当前表和目标表的键都有索引 if (a.Attribute.Navigation.IsReverse) { var ThisIndex = new ByIndex { Columns = a.Attribute.Navigation.ThisKey }; var h = IndexDict[e.Name]; if (!h.Contains(ThisIndex)) { throw new InvalidOperationException(String.Format("ThisKeyIsNotIndex: {0}->{1} FK:{2}={3}", e.Name, OtherRecordName, String.Join(", ", a.Attribute.Navigation.ThisKey), String.Join(", ", a.Attribute.Navigation.OtherKey))); } } { var OtherIndex = new ByIndex { Columns = a.Attribute.Navigation.OtherKey }; var h = IndexDict[OtherRecordName]; if (!h.Contains(OtherIndex)) { throw new InvalidOperationException(String.Format("OtherKeyIsNotIndex: {0}->{1} FK:{2}={3}", e.Name, OtherRecordName, String.Join(", ", a.Attribute.Navigation.ThisKey), String.Join(", ", a.Attribute.Navigation.OtherKey))); } } } } }