更新列类型并使用非SQL代码更新数据



我有一个Result对象表(称为Results)。目前,该表的一列是名为ResultsDatastring类型,表示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代码优先-通过迁移更改列类型。然而,这种情况下的转换代码完全是在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();
}

您的第一次编辑是正确的,您需要在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");
}

相关内容

  • 没有找到相关文章

最新更新