Fix CREATE/DROP DATABASE related issues. (#88)

pull/89/head
Laurents Meyer 5 years ago committed by GitHub
parent 00178eb0cd
commit 45e7d8a365
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -210,9 +210,7 @@ namespace EntityFrameworkCore.Jet.Data
/// </returns>
protected override DbCommand CreateDbCommand()
{
var command = JetFactory.CreateCommand();
command.Connection = this;
return command;
return CreateCommand(null);
}
/// <summary>

@ -53,8 +53,10 @@ namespace EntityFrameworkCore.Jet.Data.JetStoreSchemaDefinition
RegexOptions.IgnoreCase);
// Provider=Microsoft.ACE.OLEDB.12.0;Data Source=Joe's Database.accdb;
// Provider=Microsoft.ACE.OLEDB.12.0;Data Source="Joe's Database.accdb";
// Provider=Microsoft.ACE.OLEDB.12.0;Data Source='Joe''s Database.accdb';
_regExExtractFilenameFromConnectionString = new Regex(
@"^(?:.*;)?\s*(?:data source|dbq)\s*=\s*(?<filename>.*?)\s*(?:;|$)",
@"^(?:.*;)?\s*(?:data source|dbq)\s*=\s*(?:(?<quote>[""'])\s*(?<filename>.*?)\s*\k<quote>|(?<filename>.*?))\s*(?:;|$)",
RegexOptions.IgnoreCase);
// CREATE DATABASE Joe's Database.accdb;
@ -171,14 +173,21 @@ namespace EntityFrameworkCore.Jet.Data.JetStoreSchemaDefinition
public static string ExtractFileNameFromConnectionString(string connectionString)
{
string fileName;
Match match = _regExExtractFilenameFromConnectionString.Match(connectionString);
var match = _regExExtractFilenameFromConnectionString.Match(connectionString);
if (match.Success)
fileName = match.Groups["filename"]
.Value;
else
fileName = connectionString;
return fileName;
{
var fileName = match.Groups["filename"].Value;
if (match.Groups["quote"].Success)
{
var quoteChar = match.Groups["quote"].Value;
fileName = fileName.Replace(quoteChar + quoteChar, quoteChar);
}
return fileName;
}
return connectionString;
}
public static bool IsConnectionString(string connectionString)

@ -4,6 +4,7 @@ using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using EntityFrameworkCore.Jet.Data;
using EntityFrameworkCore.Jet.Internal;
using EntityFrameworkCore.Jet.Migrations.Operations;
using JetBrains.Annotations;
@ -101,7 +102,17 @@ namespace EntityFrameworkCore.Jet.Storage.Internal
=> _rawSqlCommandBuilder.Build(@"SELECT * FROM `INFORMATION_SCHEMA.TABLES` WHERE TABLE_TYPE IN ('BASE TABLE', 'VIEW')");
private IReadOnlyList<MigrationCommand> CreateCreateOperations()
=> Dependencies.MigrationsSqlGenerator.Generate(new[] {new JetCreateDatabaseOperation {Name = _relationalConnection.DbConnection.DataSource}});
{
var dataSource = _relationalConnection.DbConnection.DataSource;
// Alternative:
// var connection = (JetConnection) _relationalConnection.DbConnection;
// var csb = connection.JetFactory.CreateConnectionStringBuilder();
// csb.ConnectionString = connection.ConnectionString;
// var dataSource = csb.GetDataSource();
return Dependencies.MigrationsSqlGenerator.Generate(new[] {new JetCreateDatabaseOperation {Name = dataSource}});
}
/// <summary>
/// This API supports the Entity Framework Core infrastructure and is not intended to be used

@ -0,0 +1,47 @@
using System.Data.Odbc;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace EntityFrameworkCore.Jet.Data.Tests
{
[TestClass]
public class ConnectionStringTest
{
[TestMethod]
public void Escape_double_quoted_connection_string()
{
var expectedDatabaseName = "Joe's \"Recipes\" Database.accdb";
var escapedDatabaseName = expectedDatabaseName.Replace("\"", "\"\"");
var connectionString = Helpers.DataAccessProviderFactory is OdbcFactory
? $"DBQ=\"{escapedDatabaseName}\""
: $"Data Source=\"{escapedDatabaseName}\"";
var csb = Helpers.DataAccessProviderFactory.CreateConnectionStringBuilder();
csb.ConnectionString = connectionString;
var actualDatabaseName = csb.GetDataSource();
Assert.AreEqual(expectedDatabaseName, actualDatabaseName);
}
[TestMethod]
public void Escape_single_quoted_connection_string()
{
var expectedDatabaseName = "Joe's \"Recipes\" Database.accdb";
var escapedDatabaseName = expectedDatabaseName.Replace("'", "''");
var connectionString = Helpers.DataAccessProviderFactory is OdbcFactory
? $"DBQ='{escapedDatabaseName}'"
: $"Data Source='{escapedDatabaseName}'";
using var connection = new JetConnection(connectionString, Helpers.DataAccessProviderFactory);
var csb = Helpers.DataAccessProviderFactory.CreateConnectionStringBuilder();
csb.ConnectionString = connectionString;
var actualDatabaseName = csb.GetDataSource();
Assert.AreEqual(expectedDatabaseName, actualDatabaseName);
}
}
}

@ -1,4 +1,5 @@
using System.Diagnostics;
using System;
using System.Data.Odbc;
using System.IO;
using Microsoft.VisualStudio.TestTools.UnitTesting;
@ -25,31 +26,67 @@ namespace EntityFrameworkCore.Jet.Data.Tests
public void CreateAndDropDatabaseFromConnection()
{
using var connection = new JetConnection(StoreName, Helpers.DataAccessProviderFactory);
connection.CreateDatabase();
Assert.IsTrue(File.Exists(StoreName));
using var command = connection.CreateCommand();
command.CommandText = "DROP DATABASE " + StoreName;
command.ExecuteNonQuery();
connection.DropDatabase();
Assert.IsFalse(File.Exists(StoreName));
}
[TestMethod]
public void CreateAndDropDatabaseWithUnsetConnection()
{
using var connection = new JetConnection();
using var connection = new JetConnection(Helpers.DataAccessProviderFactory);
var command = connection.CreateCommand();
command.CommandText = "CREATE DATABASE " + StoreName;
command.CommandText = $"CREATE DATABASE '{StoreName}'";
command.ExecuteNonQuery();
Assert.IsTrue(File.Exists(StoreName));
command.CommandText = "DROP DATABASE " + StoreName;
command.CommandText = $"DROP DATABASE '{StoreName}'";
command.ExecuteNonQuery();
Assert.IsFalse(File.Exists(StoreName));
}
[TestMethod]
public void CreateAndDropDatabaseWithUnsetConnectionWithoutDataAccessProviderFactoryThrows()
{
using var connection = new JetConnection();
Assert.ThrowsException<InvalidOperationException>(
() => { using var command = connection.CreateCommand(); });
}
[TestMethod]
public void CreateAndDropDatabaseWithSingleQuotedConnectionString()
{
var connectionString = Helpers.DataAccessProviderFactory is OdbcFactory
? $"DBQ='{StoreName}'"
: $"Data Source='{StoreName}'";
using var connection = new JetConnection(connectionString, Helpers.DataAccessProviderFactory);
connection.CreateDatabase();
Assert.IsTrue(File.Exists(StoreName));
connection.DropDatabase();
Assert.IsFalse(File.Exists(StoreName));
}
[TestMethod]
public void CreateAndDropDatabaseWithDoubleQuotedConnectionString()
{
var connectionString = Helpers.DataAccessProviderFactory is OdbcFactory
? $"DBQ=\"{StoreName}\""
: $"Data Source=\"{StoreName}\"";
using var connection = new JetConnection(connectionString, Helpers.DataAccessProviderFactory);
connection.CreateDatabase();
Assert.IsTrue(File.Exists(StoreName));
connection.DropDatabase();
Assert.IsFalse(File.Exists(StoreName));
}
}

@ -11,11 +11,12 @@ namespace EntityFrameworkCore.Jet
{
public TestBase()
{
TestStore = JetTestStore.CreateInitialized(nameof(JetMigrationTest));
TestStore = JetTestStore.CreateInitialized(StoreName);
}
public virtual void Dispose() => TestStore.Dispose();
public virtual string StoreName => GetType().Name;
public virtual JetTestStore TestStore { get; }
public virtual List<string> SqlCommands { get; } = new List<string>();
public virtual string Sql => string.Join("\n\n", SqlCommands);

Loading…
Cancel
Save