代码之家  ›  专栏  ›  技术社区  ›  Glory Raj

有什么方法可以使这两个块具有共同的功能吗

  •  0
  • Glory Raj  · 技术社区  · 2 年前

    我有两个街区;在每个块中,我使用命令和读取器从表中检索数据,转换数据,然后更新数据。我希望通过将表名、类型和转换函数从这两个块传递给该函数来提取公共函数

    下面是相同的代码,

    //块#1

    using var queryProjectSteamSystemsCommand = dbContext.Database.GetDbConnection().CreateCommand();
    queryProjectSteamSystemsCommand.CommandText = @"SELECT ""Id""::varchar, ""InitialObject""::varchar from ""DesignHubProjectSteamSystems""";
    using var steamSystemProjectsReader = queryProjectSteamSystemsCommand.ExecuteReader();
    
    if (steamSystemProjectsReader.HasRows)
    {
        while (steamSystemProjectsReader.Read())
        {
            var id = steamSystemProjectsReader.IsDBNull(0) ? Guid.Empty : Guid.Parse(steamSystemProjectsReader.GetString(0));
            var steamSystemJson = steamSystemProjectsReader.IsDBNull(1) ? "null" : steamSystemProjectsReader.GetString(1);
            var projSteamSystemInitialObj = JsonConvert.DeserializeObject<OldSteamSystem>(steamSystemJson);
            string json = JsonConvert.SerializeObject(TransformProjectSteamSystem(projSteamSystemInitialObj)).Replace("'", "''", StringComparison.Ordinal);
            migrationBuilder.Sql($"UPDATE \"DesignHubProjectSteamSystems\"  SET \"InitialObject\" = '{json}'::jsonb WHERE \"Id\" = '{id}'");
        }
    }
    steamSystemProjectsReader.Close();
    

    //块#2

    using var queryProjectFuelSystemsCommand = dbContext.Database.GetDbConnection().CreateCommand();
    queryProjectFuelSystemsCommand.CommandText = @"SELECT ""Id""::varchar, ""InitialObject""::varchar from ""DesignHubProjectFuelSystems""";
    using var fuelSystemProjectsReader = queryProjectFuelSystemsCommand.ExecuteReader();
    
    if (fuelSystemProjectsReader.HasRows)
    {
        while (fuelSystemProjectsReader.Read())
        {
            var id = fuelSystemProjectsReader.IsDBNull(0) ? Guid.Empty : Guid.Parse(fuelSystemProjectsReader.GetString(0));
            var fuelSystemJson = fuelSystemProjectsReader.IsDBNull(1) ? "null" : fuelSystemProjectsReader.GetString(1);
            var projFuelSystemInitialObj = JsonConvert.DeserializeObject<OldFuelSystem>(fuelSystemJson);
    
            string json = JsonConvert.SerializeObject(TransformProjectFuelSystem(projFuelSystemInitialObj)).Replace("'", "''", StringComparison.Ordinal);
            migrationBuilder.Sql($"UPDATE \"DesignHubProjectFuelSystems\"  SET \"InitialObject\" = '{json}'::jsonb WHERE \"Id\" = '{id}'");
        }
    }
    fuelSystemProjectsReader.Close();
    

    我不能合并 OldSteamSystem OldFuelSystem

    那么,有谁能告诉我如何用它来实现一个公共函数吗?

    1 回复  |  直到 2 年前
        1
  •  2
  •   gunr2171    2 年前

    使用泛型,询问表名和转换对象的方法。

    void DoTheThing<TSystem>(string tableName, Func<TSystem, TSystem> transform)
    {
        using var command = dbContext.Database.GetDbConnection().CreateCommand();
        command.CommandText = @$"SELECT ""Id""::varchar, ""InitialObject""::varchar from ""{tableName}""";
        // I know I complain about SQL injection, you get to fix this one...
    
        using var reader = command.ExecuteReader();
    
        if (reader.HasRows)
        {
            while (reader.Read())
            {
                var id = reader.IsDBNull(0) ? Guid.Empty : Guid.Parse(reader.GetString(0));
                var initialJson = reader.IsDBNull(1) ? "null" : reader.GetString(1);
                var initialObj = JsonConvert.DeserializeObject<TSystem>(initialJson);
                
                // this uses the "transform" parameter, IE a method your caller provides
                string transformedJson = JsonConvert.SerializeObject(transform(initialObj)).Replace("'", "''", StringComparison.Ordinal);
                migrationBuilder.Sql($"UPDATE \"{tableName}\"  SET \"InitialObject\" = '{transformedJson}'::jsonb WHERE \"Id\" = '{id}'");
                // again, SQL injection
            }
        }
    
        reader.Close();
    }
    

    如果 transform 不同的 键入,然后将方法签名更改为

    void DoTheThing<TSystem, TTransformed>(string tableName, Func<TSystem, TTransformed> transform)