0

正如这里提到的实体框架代码优先 - Firebird 迁移:没有 MigrationSqlGenerator?我正在尝试在我的 Firebird 数据库上启用迁移。

为此,我正在编写“MigrationSqlGenerator”的以下实现(未完成!):

public class FirebirdMigrationSQLGenerator : SqlServerMigrationSqlGenerator
{
    protected override DbConnection CreateConnection()
    {
        return DbProviderFactories.GetFactory("FirebirdSql.Data.FirebirdClient").CreateConnection();
    }

    protected override void Generate(CreateTableOperation createTableOperation)
    {
        using (var writer = Writer())
        {
            WriteCreateTable(createTableOperation, writer);

            Statement(writer.InnerWriter.ToString(), true);
        }
    }

    private void WriteCreateTable(CreateTableOperation createTableOperation, IndentedTextWriter writer)
    {
        writer.WriteLine("CREATE TABLE " + Name(createTableOperation.Name) + " (");
        writer.Indent++;

        var columnCount = createTableOperation.Columns.Count();

        createTableOperation.Columns.Each(
            (c, i) =>
            {
                Generate(c, writer);

                if (i < columnCount - 1)
                {
                    writer.WriteLine(",");
                }
            });

        if (createTableOperation.PrimaryKey != null)
        {
            writer.Write(", PRIMARY KEY ");

            writer.Write("(");
            writer.Write(createTableOperation.PrimaryKey.Columns.Join(Quote));
            writer.WriteLine(")");
        }
        else
        {
            writer.WriteLine();
        }

        writer.Indent--;
        writer.Write(")");
    }

    private void Generate(ColumnModel column, IndentedTextWriter writer)
    {

        writer.Write(Quote(column.Name));
        writer.Write(" ");
        writer.Write(BuildColumnType(column));

        if ((column.IsNullable != null)
            && !column.IsNullable.Value)
        {
            writer.Write(" NOT NULL");
        }

        if (column.DefaultValue != null)
        {
            writer.Write(" DEFAULT ");
            writer.Write(Generate((dynamic)column.DefaultValue));
        }
        else if (!string.IsNullOrWhiteSpace(column.DefaultValueSql))
        {
            writer.Write(" DEFAULT ");
            writer.Write(column.DefaultValueSql);
        }
    }

    protected override void Generate(InsertHistoryOperation op)
    {
        using (var writer = Writer())
        {
            WriteinsertHistory(op, writer);
            Statement(writer.InnerWriter.ToString(), true);
        }

    }

    private void WriteinsertHistory(InsertHistoryOperation insertHistoryOperation, IndentedTextWriter writer)
    {
        StringBuilder model = new StringBuilder();

        foreach (byte item in insertHistoryOperation.Model)
            model.Append(item.ToString("X2"));

        writer.Write("INSERT INTO \"" + insertHistoryOperation.Table.ToUpper() + "\" (migrationId, model, productVersion) ");
        writer.Write(" values ( '{0}', '{1}', '{2}') ",
                          insertHistoryOperation.MigrationId,
                  "0x" + model.ToString(),
                  insertHistoryOperation.ProductVersion);

    }

    protected override string Quote(string identifier)
    {
        return identifier.Replace("PK_dbo.", "").ToUpper();
    }

    protected override string Name(string inString)
    {
        return "\"" + inString.Replace("dbo.", "").ToUpper() + "\"";
    }

    protected override string BuildColumnType(ColumnModel column)
    {
        String colType = base.BuildColumnType(column);
        if (colType == "INT")
            colType = "INTEGER";
        return colType;
    }
}

我的问题是 __MigrationHistory 表是大写的。但由于“HistoryContext”不是,第一个 SELECT 语句抛出异常:

SELECT 
"A"."A1" AS "C1"
FROM ( SELECT 
COUNT("B"."A1") AS "A1"
FROM ( SELECT 
    1 AS "A1"
    FROM "__MigrationHistory" AS "B"
)  AS "B"
)  AS "A"

通常我会在上下文中插入“modelBuilder.Conventions.Remove()”,但 HistroyContext 是框架的一部分,不能更改......

有任何想法吗?我的环境:EntityFramework 5.0.0 .NET 4.5 FirebirdClient 3.0.2.0

4

1 回答 1

1

In Firebird tablenames are only case sensitive when quoted, so you either need to stop quoting tablenames (both on creation and in queries), or you need to stop upper casing tablenames and use them as is.

For example issueing a CREATE TABLE xyz ( ... ) will create a table XYZ that can be accessed using SELECT * FROM xyz, but also with XyZ,XYZ and "XYZ". It cannot be accessed using "xyz".

Creating a table as CREATE TABLE "xyz" ( ... ) wil create a table xyz, which can only be accessed using SELECT * FROM "xyz", but not with xyz (no quotes) or any other combination of casing and with or without quotes. On the other hand CREATE TABLE "XYZ" ( ... ) can be accessed using SELECT * FROM xyz and "XYZ", and any other case without quoting, but not with SELECT * FROM "xyz".

As far as I can tell from your code, you are creating tables unquoted in WriteCreateTable, therefor the name is stored uppercase, but you are inserting into them quoted. You may also want to look into the contract/expectations of the Quote and Name methods, as it looks to me like you got their implementation reversed (Quote does what Name should do and vice versa).

于 2013-07-27T08:21:52.070 回答