protected override string GetDbProviderManifestToken(DbConnection connection)
        {
            EntityUtil.CheckArgumentNull(connection, "connection");

            SqlConnection sqlConnection = SqlProviderUtilities.GetRequiredSqlConnection(connection);

            if (string.IsNullOrEmpty(sqlConnection.ConnectionString))
            {
                throw EntityUtil.Argument(Strings.UnableToDetermineStoreVersion);
            }

            string providerManifestToken = null;

            // Try to get the provider manifest token from the database connection
            // That failing, try using connection to master database (in case the database doesn't exist yet)
            try
            {
                UsingConnection(sqlConnection, conn =>
                {
                    providerManifestToken = SqlVersionUtils.GetVersionHint(SqlVersionUtils.GetSqlVersion(conn));
                });
            }
            catch
            {
                UsingMasterConnection(sqlConnection, conn =>
                {
                    providerManifestToken = SqlVersionUtils.GetVersionHint(SqlVersionUtils.GetSqlVersion(conn));
                });
            }
            return(providerManifestToken);
        }
        protected override string DbCreateDatabaseScript(string providerManifestToken, StoreItemCollection storeItemCollection)
        {
            EntityUtil.CheckArgumentNull(providerManifestToken, "providerManifestToken");
            EntityUtil.CheckArgumentNull(storeItemCollection, "storeItemCollection");
            SqlVersion version = SqlVersionUtils.GetSqlVersion(providerManifestToken);

            return(CreateObjectsScript(version, storeItemCollection));
        }
        /// <summary>
        /// Determines whether the database for the given connection exists.
        /// There are three cases:
        /// 1.  Initial Catalog = X, AttachDBFilename = null:   (SELECT Count(*) FROM sys.databases WHERE [name]= X) > 0
        /// 2.  Initial Catalog = X, AttachDBFilename = F:      if (SELECT Count(*) FROM sys.databases WHERE [name]= X) >  true,
        /// if not, try to open the connection and then return (SELECT Count(*) FROM sys.databases WHERE [name]= X) > 0
        /// 3.  Initial Catalog = null, AttachDBFilename = F:   Try to open the connection. If that succeeds the result is true, otherwise
        /// if the there are no databases corresponding to the given file return false, otherwise throw.
        ///
        /// Note: We open the connection to cover the scenario when the mdf exists, but is not attached.
        /// Given that opening the connection would auto-attach it, it would not be appropriate to return false in this case.
        /// Also note that checking for the existence of the file does not work for a remote server.  (Dev11 #290487)
        /// For further details on the behavior when AttachDBFilename is specified see Dev10# 188936
        /// </summary>
        protected override bool DbDatabaseExists(DbConnection connection, int?commandTimeout, StoreItemCollection storeItemCollection)
        {
            EntityUtil.CheckArgumentNull(connection, "connection");
            EntityUtil.CheckArgumentNull(storeItemCollection, "storeItemCollection");

            SqlConnection sqlConnection     = SqlProviderUtilities.GetRequiredSqlConnection(connection);
            var           connectionBuilder = new SqlConnectionStringBuilder(sqlConnection.ConnectionString);

            if (string.IsNullOrEmpty(connectionBuilder.InitialCatalog) && string.IsNullOrEmpty(connectionBuilder.AttachDBFilename))
            {
                throw EntityUtil.InvalidOperation(Strings.SqlProvider_DdlGeneration_MissingInitialCatalog);
            }

            if (!string.IsNullOrEmpty(connectionBuilder.InitialCatalog))
            {
                if (CheckDatabaseExists(sqlConnection, commandTimeout, connectionBuilder.InitialCatalog))
                {
                    //Avoid further processing
                    return(true);
                }
            }

            if (!string.IsNullOrEmpty(connectionBuilder.AttachDBFilename))
            {
                try
                {
                    UsingConnection(sqlConnection, (SqlConnection con) => { });
                    return(true);
                }
                catch (SqlException e)
                {
                    if (!string.IsNullOrEmpty(connectionBuilder.InitialCatalog))
                    {
                        return(CheckDatabaseExists(sqlConnection, commandTimeout, connectionBuilder.InitialCatalog));
                    }
                    // Initial catalog not specified
                    string fileName = GetMdfFileName(connectionBuilder.AttachDBFilename);
                    bool   databaseDoesNotExistInSysTables = false;
                    UsingMasterConnection(sqlConnection, conn =>
                    {
                        SqlVersion sqlVersion       = SqlVersionUtils.GetSqlVersion(conn);
                        string databaseExistsScript = SqlDdlBuilder.CreateCountDatabasesBasedOnFileNameScript(fileName, useDeprecatedSystemTable: sqlVersion == SqlVersion.Sql8);
                        int result = (int)CreateCommand(conn, databaseExistsScript, commandTimeout).ExecuteScalar();
                        databaseDoesNotExistInSysTables = (result == 0);
                    });
                    if (databaseDoesNotExistInSysTables)
                    {
                        return(false);
                    }
                    throw EntityUtil.InvalidOperation(Strings.SqlProvider_DdlGeneration_CannotTellIfDatabaseExists, e);
                }
            }

            // CheckDatabaseExists returned false and no AttachDBFilename is specified
            return(false);
        }
        /// <summary>
        /// Delete the database for the given connection.
        /// There are three cases:
        /// 1.  If Initial Catalog is specified (X) drop database X
        /// 2.  Else if AttachDBFilename is specified (F) drop all the databases corresponding to F
        /// if none throw
        /// 3.  If niether the catalog not the file name is specified - throw
        ///
        /// Note that directly deleting the files does not work for a remote server.  However, even for not attached
        /// databases the current logic would work assuming the user does: if (DatabaseExists) DeleteDatabase
        /// </summary>
        /// <param name="connection"></param>
        /// <param name="commandTimeout"></param>
        /// <param name="storeItemCollection"></param>
        protected override void DbDeleteDatabase(DbConnection connection, int?commandTimeout, StoreItemCollection storeItemCollection)
        {
            EntityUtil.CheckArgumentNull(connection, "connection");
            EntityUtil.CheckArgumentNull(storeItemCollection, "storeItemCollection");
            SqlConnection sqlConnection = SqlProviderUtilities.GetRequiredSqlConnection(connection);

            var    connectionBuilder = new SqlConnectionStringBuilder(sqlConnection.ConnectionString);
            string initialCatalog    = connectionBuilder.InitialCatalog;
            string attachDBFile      = connectionBuilder.AttachDBFilename;

            if (!string.IsNullOrEmpty(initialCatalog))
            {
                DropDatabase(sqlConnection, commandTimeout, initialCatalog);
            }

            // initial catalog not specified
            else if (!string.IsNullOrEmpty(attachDBFile))
            {
                string fullFileName = GetMdfFileName(attachDBFile);

                List <string> databaseNames = new List <string>();
                UsingMasterConnection(sqlConnection, conn =>
                {
                    SqlVersion sqlVersion         = SqlVersionUtils.GetSqlVersion(conn);
                    string getDatabaseNamesScript = SqlDdlBuilder.CreateGetDatabaseNamesBasedOnFileNameScript(fullFileName, sqlVersion == SqlVersion.Sql8);
                    var command = CreateCommand(conn, getDatabaseNamesScript, commandTimeout);
                    using (var reader = command.ExecuteReader())
                    {
                        while (reader.Read())
                        {
                            databaseNames.Add(reader.GetString(0));
                        }
                    }
                });
                if (databaseNames.Count > 0)
                {
                    foreach (var databaseName in databaseNames)
                    {
                        DropDatabase(sqlConnection, commandTimeout, databaseName);
                    }
                }
                else
                {
                    throw EntityUtil.InvalidOperation(Strings.SqlProvider_DdlGeneration_CannotDeleteDatabaseNoInitialCatalog);
                }
            }
            // neither initial catalog nor attachDB file name are specified
            else
            {
                throw EntityUtil.InvalidOperation(Strings.SqlProvider_DdlGeneration_MissingInitialCatalog);
            }
        }
        private static bool CheckDatabaseExists(SqlConnection sqlConnection, int?commandTimeout, string databaseName)
        {
            bool databaseExistsInSysTables = false;

            UsingMasterConnection(sqlConnection, conn =>
            {
                SqlVersion sqlVersion       = SqlVersionUtils.GetSqlVersion(conn);
                string databaseExistsScript = SqlDdlBuilder.CreateDatabaseExistsScript(databaseName, useDeprecatedSystemTable: sqlVersion == SqlVersion.Sql8);
                int result = (int)CreateCommand(conn, databaseExistsScript, commandTimeout).ExecuteScalar();
                databaseExistsInSysTables = (result > 0);
            });
            return(databaseExistsInSysTables);
        }
        void ValidateVersionHint(string versionHint)
        {
            if (string.IsNullOrEmpty(versionHint))
            {
                throw EntityUtil.Argument(Strings.UnableToDetermineStoreVersion);
            }

            // GetSqlVersion will throw ArgumentException if manifestToken is null, empty, or not recognized.
            SqlVersion tokenVersion = SqlVersionUtils.GetSqlVersion(versionHint);

            // SQL spatial support is only available for SQL Server 2008 and later
            if (tokenVersion < SqlVersion.Sql10)
            {
                throw EntityUtil.ProviderIncompatible(Strings.SqlProvider_Sql2008RequiredForSpatial);
            }
        }
Beispiel #7
0
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="manifestToken">A token used to infer the capabilities of the store</param>
 public SqlProviderManifest(string manifestToken)
     : base(SqlProviderManifest.GetProviderManifest())
 {
     // GetSqlVersion will throw ArgumentException if manifestToken is null, empty, or not recognized.
     _version = SqlVersionUtils.GetSqlVersion(manifestToken);
 }
        /// <summary>
        /// Determines SqlDbType for the given primitive type. Extracts facet
        /// information as well.
        /// </summary>
        private static SqlDbType GetSqlDbType(TypeUsage type, bool isOutParam, SqlVersion version, out int?size, out byte?precision, out byte?scale, out string udtName)
        {
            // only supported for primitive type
            PrimitiveTypeKind primitiveTypeKind = MetadataHelper.GetPrimitiveTypeKind(type);

            size      = default(int?);
            precision = default(byte?);
            scale     = default(byte?);
            udtName   = default(string);

            //
            switch (primitiveTypeKind)
            {
            case PrimitiveTypeKind.Binary:
                // for output parameters, ensure there is space...
                size = GetParameterSize(type, isOutParam);
                return(GetBinaryDbType(type));

            case PrimitiveTypeKind.Boolean:
                return(SqlDbType.Bit);

            case PrimitiveTypeKind.Byte:
                return(SqlDbType.TinyInt);

            case PrimitiveTypeKind.Time:
                if (!SqlVersionUtils.IsPreKatmai(version))
                {
                    precision = GetKatmaiDateTimePrecision(type, isOutParam);
                }
                return(SqlDbType.Time);

            case PrimitiveTypeKind.DateTimeOffset:
                if (!SqlVersionUtils.IsPreKatmai(version))
                {
                    precision = GetKatmaiDateTimePrecision(type, isOutParam);
                }
                return(SqlDbType.DateTimeOffset);

            case PrimitiveTypeKind.DateTime:
                //For katmai pick the type with max precision which is datetime2
                if (!SqlVersionUtils.IsPreKatmai(version))
                {
                    precision = GetKatmaiDateTimePrecision(type, isOutParam);
                    return(SqlDbType.DateTime2);
                }
                else
                {
                    return(SqlDbType.DateTime);
                }

            case PrimitiveTypeKind.Decimal:
                precision = GetParameterPrecision(type, null);
                scale     = GetScale(type);
                return(SqlDbType.Decimal);

            case PrimitiveTypeKind.Double:
                return(SqlDbType.Float);

            case PrimitiveTypeKind.Geography:
            {
                udtName = "geography";
                return(SqlDbType.Udt);
            }

            case PrimitiveTypeKind.Geometry:
            {
                udtName = "geometry";
                return(SqlDbType.Udt);
            }

            case PrimitiveTypeKind.Guid:
                return(SqlDbType.UniqueIdentifier);

            case PrimitiveTypeKind.Int16:
                return(SqlDbType.SmallInt);

            case PrimitiveTypeKind.Int32:
                return(SqlDbType.Int);

            case PrimitiveTypeKind.Int64:
                return(SqlDbType.BigInt);

            case PrimitiveTypeKind.SByte:
                return(SqlDbType.SmallInt);

            case PrimitiveTypeKind.Single:
                return(SqlDbType.Real);

            case PrimitiveTypeKind.String:
                size = GetParameterSize(type, isOutParam);
                return(GetStringDbType(type));

            default:
                Debug.Fail("unknown PrimitiveTypeKind " + primitiveTypeKind);
                return(SqlDbType.Variant);
            }
        }