【问题标题】:Updating a column type and updating data with non-SQL code使用非 SQL 代码更新列类型和更新数据
【发布时间】:2015-04-03 10:52:31
【问题描述】:

我有一个Result 对象表(称为Results)。目前,该表的一列是 string 类型,称为 ResultsData,表示 C# 对象的 Json 序列化(使用 Json.NET)。

由于这些对象的大小问题导致数据库查询超时,我想将此列更改为byte[],保存对象的 Bson 序列化。但是,当我更改类型、添加迁移并运行它时,它可以理解地崩溃,因为string 对象没有隐式转换为byte[]。用于迁移的Up() 方法,供参考,如下所示:

public override void Up()
{
    AlterColumn("dbo.Results", "ResultsData", c => c.Binary());
}

我应该提到,这里的任何数据丢失都是不可接受的。

现在我可以处理将单个字符串转换为字节数组的代码,它位于我们将调用byte[] ConvertResult(string resultsData) 的方法中。我不确定如何在数据库的每一行上调用此方法。

我在这里能找到的最接近的答案是这个问题的第一个答案:EF5 Code First - Changing A Column Type With Migrations。但是,这种情况下的转换代码完全是在 SQL 中完成的,这里显然不适用。

如果有人对我如何解决此问题有任何想法,我们将不胜感激。我正在运行的实体框架版本是 6.1.3,如果有帮助的话。

编辑

无奈之下,我尝试将实际转换代码放入SQL方法中:没想到它可以工作,它没有,产生错误Incorrect syntax near 'END'

public override void Up()
{
    AddColumn("dbo.Results", "ResultsDataTmp", c => c.Binary());
    Sql(@"
    UPDATE dbo.Results
    SET ResultsDataTmp = Service.ConvertOldResultsToBinary(ResultsData)
        END
    ");
    DropColumn("dbo.Results", "ResultsData");
    RenameColumn("dbo.Results", "ResultsDataTmp", "ResultsData");
}

编辑 2

根据 DrewJordan 的要求,这是 Serial.ConvertOldResultsToBinary 的实现。

public byte[] ConvertOldResultsToBinary (string oldResultsData)
{
    var serializer = new JsonSerializer
    {
        ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor,
        TypeNameHandling = TypeNameHandling.Auto,
        MissingMemberHandling = MissingMemberHandling.Ignore
    };

    IResultsWrapper result;

    using (var reader = new JsonTextReader(new StringReader(oldResultsData)))
    {
        try
        {
            result = serializer.Deserialize<ResultsWrapper>(reader);
        }
        catch (JsonSerializationException)
        {
            using (var trialReader = new JsonTextReader(new StringReader(oldResultsData)))
                {
                    result = serializer.Deserialize<TrialResultsWrapper>(trialReader);
            }
        }
    }

    var stream = new MemoryStream();
    using (var writer = new BsonWriter(stream))
    {
        serializer.Serialize(writer, result);
    }
    return stream.ToArray();
}

【问题讨论】:

  • 如果有帮助,给出的具体错误是:Implicit conversion from data type nvarchar(max) to varbinary(max) is not allowed. Use the CONVERT function to run this query.
  • Service.ConvertOldResultsToBinary 中做了什么?可以发一下吗?
  • @DrewJordan 抱歉回复晚了,刚刚编辑了问题以包含此代码。感谢您的关注。

标签: c# json entity-framework json.net


【解决方案1】:

您的第一次编辑在正确的轨道上,您需要在 SQL 中转换为二进制文件,但是您不能在对 Sql() 的调用中调用 C# 代码,因为您告诉它只需运行您传递的字符串作为 SQL 命令。

试试这样的:

public override void Up()
{
    AddColumn("dbo.Results", "ResultsDataTmp", c => c.Binary());
    Sql(@"
    UPDATE dbo.Results
    SET ResultsDataTmp = CAST(ResultsData AS VARBINARY(MAX))
        END
    ");
    DropColumn("dbo.Results", "ResultsData");
    RenameColumn("dbo.Results", "ResultsDataTmp", "ResultsData");
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-03
    • 1970-01-01
    • 1970-01-01
    • 2011-08-20
    • 1970-01-01
    相关资源
    最近更新 更多