#region MIT license // // MIT license // // Copyright (c) 2007-2008 Jiri Moudry, Pascal Craponne // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // #endregion using System.Data; using System.Linq; using DbLinq.Schema; using DbLinq.Schema.Dbml; namespace DbLinq.Vendor.Implementation { partial class SchemaLoader { /// /// Loads the constraints. /// /// The schema. /// Name of the schema. /// The conn. /// The name format. /// The names. protected abstract void LoadConstraints(Database schema, SchemaName schemaName, IDbConnection conn, NameFormat nameFormat, Names names); /// /// Loads the foreign key. /// /// The schema. /// The table. /// Name of the column. /// Name of the table. /// The table schema. /// Name of the referenced column. /// Name of the referenced table. /// The referenced table schema. /// Name of the constraint. /// The name format. /// The names. protected virtual void LoadForeignKey(Database schema, Table table, string columnName, string tableName, string tableSchema, string referencedColumnName, string referencedTableName, string referencedTableSchema, string constraintName, NameFormat nameFormat, Names names) { var foreignKey = names.ColumnsNames[tableName][columnName].PropertyName; var reverseForeignKey = names.ColumnsNames[referencedTableName][referencedColumnName].PropertyName; var associationName = CreateAssociationName(tableName, tableSchema, referencedTableName, referencedTableSchema, constraintName, foreignKey, nameFormat); //both parent and child table get an [Association] var assoc = new Association(); assoc.IsForeignKey = true; assoc.Name = constraintName; assoc.Type = null; assoc.ThisKey = foreignKey; assoc.OtherKey = reverseForeignKey; assoc.Member = associationName.ManyToOneMemberName; assoc.Cardinality = Cardinality.Many; // TODO: check this is the right direction (even if it appears to be useless) table.Type.Associations.Add(assoc); //and insert the reverse association: var reverseAssociation = new Association(); reverseAssociation.Name = constraintName; reverseAssociation.Type = table.Type.Name; reverseAssociation.Member = associationName.OneToManyMemberName; reverseAssociation.Cardinality = Cardinality.One; reverseAssociation.ThisKey = reverseForeignKey; reverseAssociation.OtherKey = foreignKey; reverseAssociation.DeleteRule = "NO ACTION"; string referencedFullDbName = GetFullDbName(referencedTableName, referencedTableSchema); var referencedTable = schema.Tables.FirstOrDefault(t => referencedFullDbName == t.Name); if (referencedTable == null) { //try case-insensitive match //reason: MySql's Key_Column_Usage table contains both 'Northwind' and 'northwind' referencedTable = schema.Tables.FirstOrDefault(t => referencedFullDbName.ToLower() == t.Name.ToLower()); } if (referencedTable == null) { ReportForeignKeyError(schema, referencedFullDbName); } else { referencedTable.Type.Associations.Add(reverseAssociation); assoc.Type = referencedTable.Type.Name; } } /// /// Reports a foreign key error. /// /// The schema. /// The referenced table full. private void ReportForeignKeyError(Database schema, string referencedTableFull) { var tablesMap = schema.Tables.ToDictionary(t => t.Name.ToLower()); var referencedTableFullL = referencedTableFull.ToLower(); string msg = "ERROR L91: parent table not found: " + referencedTableFull; Table matchedTable; if (tablesMap.TryGetValue(referencedTableFullL, out matchedTable)) { //case problems arise from various reasons, //e.g. different capitalization on WIndows vs Linux, //bugs in DbLinq etc msg += " - however, schema lists a table spelled as " + matchedTable.Name; } WriteErrorLine(msg); } } }