public virtual void SetSqlGenerator(string providerInvariantName, MigrationSqlGenerator migrationSqlGenerator)
        {
            Contract.Requires(!string.IsNullOrWhiteSpace(providerInvariantName));
            Contract.Requires(migrationSqlGenerator != null);

            _sqlGenerators[providerInvariantName] = migrationSqlGenerator;
        }
        /// <summary>
        ///     Adds a new SQL generator to be used for a given database provider.
        /// </summary>
        /// <param name = "providerInvariantName">Name of the database provider to set the SQL generator for.</param>
        /// <param name = "migrationSqlGenerator">The SQL generator to be used.</param>
        public void SetSqlGenerator(string providerInvariantName, MigrationSqlGenerator migrationSqlGenerator)
        {
            Contract.Requires(!string.IsNullOrWhiteSpace(providerInvariantName));
            Contract.Requires(migrationSqlGenerator != null);

            _mainConfiguration.Value.RootResolver.MigrationsConfigurationResolver.SetSqlGenerator(
                providerInvariantName,
                migrationSqlGenerator);
        }
        public IEnumerable<MigrationOperation> Diff(
            XDocument sourceModel,
            XDocument targetModel,
            ModificationCommandTreeGenerator modificationCommandTreeGenerator = null,
            MigrationSqlGenerator migrationSqlGenerator = null)
        {
            DebugCheck.NotNull(sourceModel);
            DebugCheck.NotNull(targetModel);

            DbProviderInfo providerInfo;

            var storageMappingItemCollection
                = sourceModel.GetStorageMappingItemCollection(out providerInfo);

            var source
                = new ModelMetadata
                      {
                          Model = sourceModel,
                          StoreItemCollection = storageMappingItemCollection.StoreItemCollection,
                          StorageEntityContainerMapping
                              = storageMappingItemCollection.GetItems<StorageEntityContainerMapping>().Single(),
                          ProviderManifest = GetProviderManifest(providerInfo),
                          ProviderInfo = providerInfo
                      };

            storageMappingItemCollection
                = targetModel.GetStorageMappingItemCollection(out providerInfo);

            var target
                = new ModelMetadata
                      {
                          Model = targetModel,
                          StoreItemCollection = storageMappingItemCollection.StoreItemCollection,
                          StorageEntityContainerMapping
                              = storageMappingItemCollection.GetItems<StorageEntityContainerMapping>().Single(),
                          ProviderManifest = GetProviderManifest(providerInfo),
                          ProviderInfo = providerInfo
                      };

            return Diff(source, target, modificationCommandTreeGenerator, migrationSqlGenerator);
        }
        /// <summary>
        /// Adds a new SQL generator to be used for a given database provider.
        /// </summary>
        /// <param name="providerInvariantName"> Name of the database provider to set the SQL generator for. </param>
        /// <param name="migrationSqlGenerator"> The SQL generator to be used. </param>
        public void SetSqlGenerator(string providerInvariantName, MigrationSqlGenerator migrationSqlGenerator)
        {
            Check.NotEmpty(providerInvariantName, "providerInvariantName");
            Check.NotNull(migrationSqlGenerator, "migrationSqlGenerator");

            _sqlGenerators[providerInvariantName] = migrationSqlGenerator;
        }
        /// <summary>
        ///     For testing.
        /// </summary>
        public IEnumerable<MigrationOperation> Diff(
            ModelMetadata source,
            ModelMetadata target,
            ModificationCommandTreeGenerator modificationCommandTreeGenerator,
            MigrationSqlGenerator migrationSqlGenerator)
        {
            DebugCheck.NotNull(source);
            DebugCheck.NotNull(target);

            _source = source;
            _target = target;

            _consistentProviders
                = _source.ProviderInfo.ProviderInvariantName.EqualsIgnoreCase(
                    _target.ProviderInfo.ProviderInvariantName)
                  && _source.ProviderInfo.ProviderManifestToken.EqualsIgnoreCase(
                      _target.ProviderInfo.ProviderManifestToken);

            var renamedColumns = FindRenamedColumns().ToList();
            var addedColumns = FindAddedColumns(renamedColumns).ToList();
            var alteredColumns = FindChangedColumns().ToList();
            var removedColumns = FindRemovedColumns(renamedColumns).ToList();
            var renamedTables = FindRenamedTables().ToList();
            var movedTables = FindMovedTables().ToList();
            var addedTables = FindAddedTables(renamedTables).ToList();

            var columnNormalizedSourceModel = BuildColumnNormalizedSourceModel(renamedColumns);

            var addedForeignKeys = FindAddedForeignKeys(columnNormalizedSourceModel).ToList();
            var removedTables = FindRemovedTables(renamedTables).ToList();
            var removedForeignKeys = FindRemovedForeignKeys(columnNormalizedSourceModel).ToList();
            var changedPrimaryKeys = FindChangedPrimaryKeys(columnNormalizedSourceModel).ToList();

            var addedModificationFunctions
                = FindAddedModificationFunctions(modificationCommandTreeGenerator, migrationSqlGenerator)
                    .ToList();

            var removedModificationFunctions = FindRemovedModificationFunctions().ToList();

            return renamedTables
                .Concat<MigrationOperation>(movedTables)
                .Concat(removedForeignKeys)
                .Concat(removedForeignKeys.Select(fko => fko.CreateDropIndexOperation()))
                .Concat(renamedColumns)
                .Concat(addedTables)
                .Concat(addedColumns)
                .Concat(alteredColumns)
                .Concat(changedPrimaryKeys)
                .Concat(addedForeignKeys.Select(fko => fko.CreateCreateIndexOperation()))
                .Concat(addedForeignKeys)
                .Concat(removedColumns)
                .Concat(removedTables)
                .Concat(addedModificationFunctions)
                .Concat(removedModificationFunctions)
                .ToList();
        }
        private IEnumerable<CreateProcedureOperation> BuildCreateProcedureOperations(
            StorageAssociationSetModificationFunctionMapping modificationFunctionMapping,
            ModificationCommandTreeGenerator modificationCommandTreeGenerator,
            MigrationSqlGenerator migrationSqlGenerator)
        {
            DebugCheck.NotNull(modificationFunctionMapping);

            var insertCommandTrees = new DbInsertCommandTree[0];
            var deleteCommandTrees = new DbDeleteCommandTree[0];

            if (modificationCommandTreeGenerator != null)
            {
                var dynamicToFunctionModificationCommandConverter
                    = new DynamicToFunctionModificationCommandConverter(
                        modificationFunctionMapping,
                        _target.StorageEntityContainerMapping);

                insertCommandTrees
                    = dynamicToFunctionModificationCommandConverter
                        .Convert(
                            modificationCommandTreeGenerator
                                .GenerateAssociationInsert(modificationFunctionMapping.AssociationSet.ElementType.Identity))
                        .ToArray();

                deleteCommandTrees
                    = dynamicToFunctionModificationCommandConverter
                        .Convert(
                            modificationCommandTreeGenerator
                                .GenerateAssociationDelete(modificationFunctionMapping.AssociationSet.ElementType.Identity))
                        .ToArray();
            }

            string insertBodySql = null, deleteBodySql = null;

            if (migrationSqlGenerator != null)
            {
                var providerManifestToken
                    = _target.ProviderInfo.ProviderManifestToken;

                insertBodySql
                    = migrationSqlGenerator
                        .GenerateProcedureBody(insertCommandTrees, null, providerManifestToken);

                deleteBodySql
                    = migrationSqlGenerator.GenerateProcedureBody(
                        deleteCommandTrees,
                        modificationFunctionMapping.DeleteFunctionMapping.RowsAffectedParameterName,
                        providerManifestToken);
            }

            yield return BuildCreateProcedureOperation(
                modificationFunctionMapping.InsertFunctionMapping.Function,
                insertBodySql);

            yield return BuildCreateProcedureOperation(
                modificationFunctionMapping.DeleteFunctionMapping.Function,
                deleteBodySql);
        }
 private IEnumerable<CreateProcedureOperation> FindAddedModificationFunctions(
     ModificationCommandTreeGenerator modificationCommandTreeGenerator, MigrationSqlGenerator migrationSqlGenerator)
 {
     return
         (from esm1 in _target.StorageEntityContainerMapping.EntitySetMappings
          from mfm1 in esm1.ModificationFunctionMappings
          where !(from esm2 in _source.StorageEntityContainerMapping.EntitySetMappings
                  from mfm2 in esm2.ModificationFunctionMappings
                  where mfm1.EntityType.Identity == mfm2.EntityType.Identity
                  select mfm2
                 ).Any()
          from o in BuildCreateProcedureOperations(mfm1, modificationCommandTreeGenerator, migrationSqlGenerator)
          select o)
             .Concat(
                 from asm1 in _target.StorageEntityContainerMapping.AssociationSetMappings
                 where asm1.ModificationFunctionMapping != null
                 where !(from asm2 in _source.StorageEntityContainerMapping.AssociationSetMappings
                         where asm2.ModificationFunctionMapping != null
                               && asm1.ModificationFunctionMapping.AssociationSet.Identity
                               == asm2.ModificationFunctionMapping.AssociationSet.Identity
                         select asm2.ModificationFunctionMapping
                        ).Any()
                 from o in BuildCreateProcedureOperations(
                     asm1.ModificationFunctionMapping,
                     modificationCommandTreeGenerator,
                     migrationSqlGenerator)
                 select o);
 }