public void FixtureSetup() { using (var db = new TestEf6SchemaCompareDb()) { var decoder = new Ef6MetadataDecoder(Assembly.GetAssembly(typeof(DataTop))); _efInfos = decoder.GetAllEfTablesWithColInfo(db); var allSqlInfo = SqlAllInfo.SqlAllInfoFactory(db.Database.Connection.ConnectionString); _checker = new EfRelationshipChecker(_efInfos, allSqlInfo, allSqlInfo.TableInfos); //NOTE: we aren't able to filter potentialManyToManyTables } }
public ISuccessOrErrors CompareEfWithSql(IList <EfTableInfo> efInfos, SqlAllInfo allSqlInfo) { var status = SuccessOrErrors.Success("All Ok"); //first we compare the ef table columns with the SQL table columns foreach (var efInfo in efInfos) { if (!_sqlInfoDict.ContainsKey(efInfo.CombinedName)) { status.AddSingleError( "Missing Table: The SQL {0} does not contain a table called {1}. Needed by EF class {2}.", _sqlDbRefString, efInfo.CombinedName, efInfo.ClrClassType.Name); } else { //has table, so compare the columns/properties var sqlTableInfo = _sqlInfoDict[efInfo.CombinedName]; _sqlInfoDict.Remove(efInfo.CombinedName); //we create a dict, which we check. As we find columns we remove them var sqlColsDict = sqlTableInfo.ColumnInfos.ToDictionary(x => x.ColumnName); foreach (var clrCol in efInfo.NormalCols) { if (!sqlColsDict.ContainsKey(clrCol.SqlColumnName)) { status.AddSingleError( "Missing Column: The SQL {0} table {1} does not contain a column called {2}. Needed by EF class {3}.", _sqlDbRefString, efInfo.CombinedName, clrCol.SqlColumnName, efInfo.ClrClassType.Name); } else { //check the columns match var sqlCol = sqlColsDict[clrCol.SqlColumnName]; sqlColsDict.Remove(clrCol.SqlColumnName); //remove it as it has been used status.Combine(CheckColumn(sqlCol, clrCol, efInfo.CombinedName)); } } //At the end we check if any sql columns are left if (sqlColsDict.Any()) { foreach (var missingCol in sqlColsDict.Values) { status.AddWarning("SQL {0} table {1} has a column called {2} (.NET type {3}) that EF does not access.", _sqlDbRefString, efInfo.CombinedName, missingCol.ColumnName, missingCol.SqlTypeName.SqlToClrType(missingCol.IsNullable)); } } } } //now we compare the EF relationships with the SQL foreign keys //we do this here because we now have the tables that wren't mentioned in EF, //which are the tables that EF will automatically add to handle many-many relationships. var relChecker = new EfRelationshipChecker(efInfos, allSqlInfo, _sqlInfoDict.Values.ToList()); foreach (var efInfo in efInfos) { //now we check the relationships foreach (var relationCol in efInfo.RelationshipCols) { var relStatus = relChecker.CheckEfRelationshipToSql(efInfo, relationCol); status.Combine(relStatus); if (relStatus.IsValid && relStatus.Result != null) { //It has found a many-to-many table which we need to remove so that it does not show a warning at the end _sqlInfoDict.Remove(relStatus.Result); } } } return(status); }