【问题标题】:RhinoETL merge table with webservice resultsRhino ETL 合并表与 Web 服务结果
【发布时间】:2014-03-23 23:26:53
【问题描述】:

我在 SQL Server 中有一个从 Web 服务填充的表。我希望它按计划刷新。我想要一些类似于 SQL 合并操作的东西。

也就是说,我定义了我的源(Web 服务)和我的目标(SQL 表),并且我定义了如何处理目标和匹配中的源缺失。

让我们考虑一个场景,我在表 Description 和 Deleted 中只有两个字段,并且 Web 服务只提供 Description。

  • 如果表和 Web 服务中都存在描述,那么我只是更新(或不更新)。

  • 如果描述存在于 Web 服务中但不在表中,我希望将其插入

  • 如果 Web 服务器中不再存在描述,我希望将其标记为 Deleted = true

我目前拥有的是:

public class WebServiceResults: AbstractOperation
{
    public WebServiceResults()
    {
        var WebService = new WebService();
        WSResults = WebService.GetResults();
    }
    IEnumerable<WSResult> WSResults  { get; set; }
    public override IEnumerable<Row> Execute(IEnumerable<Row> rows)
    {
        foreach(var obj in WSResults)
            yield return Row.FromObject(obj);
    }

}

class SQLTableResults : AbstractOperation
{
    public SQLTableResults()
    {
        SQLResults = data.MyTable.Select(x=>new {x.Description,x.Deletet});
    }
    Data data = new Data();
    IEnumerable<SQLResult> SQLResults  { get; set; }
    public override IEnumerable<Row> Execute(IEnumerable<Row> rows)
    {
        foreach (var obj in SQLResults)
            yield return Row.FromObject(obj);
        }
    }
    public override void Dispose()
    {
        data.Dispose();
        base.Dispose();
    }
}

class JoinTables : JoinOperation
{

    protected override Row MergeRows(Row leftRow, Row rightRow)
    {
        Row row = leftRow.Clone();
        row["Description2"] = rightRow["Description"];
        return row;
    }

    protected override void SetupJoinConditions()
    {
        FullOuterJoin
            .Left("Description")
            .Right("Description");
    }
}

class MergeTables : AbstractOperation
{
    Data data = new Data();
    public MergeTables()
    { }

    public override IEnumerable<Row> Execute(IEnumerable<Row> rows)
    {
        foreach (var obj in rows)
        {
            if (String.IsNullOrEmpty((string)obj["Description2"]))
            {
                //Code for not matched at target
                yield return Row.FromObject(obj);
            }
            if (String.IsNullOrEmpty((string)obj["Description"]))
            {
                //Code for not matched at source
                yield return Row.FromObject(obj);
            }

            {
                //Code for matched
                yield return Row.FromObject(obj);
            }
        }
    }
    public override void Dispose()
    {
        data.Dispose();
        base.Dispose();
    }
}

protected override void Initialize()
{
    Register(
           new JoinTables()
           .Left(new SQLTableResults())
           .Right(new WebServiceResults())
       );
    Register(new MergeTables());
    foreach (var error in GetAllErrors())
        Console.Write(error.Message);
}

这是要走的路吗?我会想象更多的逐步过程,例如

Register(new NotMatchedAtSourceOperation());
Register(new NotMatchedAtTargetOperation());
Register(new MatchedOperation());

但据我了解,每个寄存器将其行返回到下一个,所以如果我过滤不匹配的,那么其他两个将什么也不做。

我应该为每个案例创建一个新流程吗?

顺便说一句,我正在寻找有关 RhinoEtl 的文档。你知道任何链接吗?有教程吗?

【问题讨论】:

    标签: c# rhino-etl


    【解决方案1】:

    使用完全外连接在单个操作中确定合并操作。你可以看到一个例子here。这不完全是您所需要的,所以我会尝试在下面根据您的情况进行调整:

    protected override Row MergeRows(Row wsRow, Row dbRow) {
    
        Row row;
    
        // if the db row doesn't exist, then the ws row is new, and it should be inserted
        if (dbRow["id"] == null) {
            row = wsRow.Clone();
            row["action"] = "Insert";
            row["deleted"] = false;
            return row;
        }
    
        // if the ws row doesn't exist, it should be marked as deleted in the database (if not already)
        if (wsRow["id"] == null) {
            row = dbRow.Clone();
            row["deleted"] = true;
            row["action"] = dbRow["deleted"].Equals(true) ? "None" : "Update";
            return row;
        }
    
        // ws and db descriptions match, but check and make sure it's not marked as deleted in database
        row = wsRow.Clone();
        row["deleted"] = false;
        row["action"] = dbRow["deleted"].Equals(true) ? "Update" : "None";
        return row;
    
    }
    
    protected override void SetupJoinConditions() {
        FullOuterJoin.Left("description").Right("description");
    }
    

    运行此操作后,每一行都会有“插入”、“更新”或“无”的操作。基于此操作,您可以编写要执行的 SqlBatchOperation 的插入和更新语句。

    【讨论】:

    • 抱歉这么久才回复。这就是我一直在寻找的。我能看到的唯一缺点是我们不能利用 IEnumerable 所以我们最终首先“解析”了整个数据集。另一方面,我无法找到一种使用 IEnumerable 执行此操作的方法,而无需事先解析它们......无论如何,谢谢。
    猜你喜欢
    • 1970-01-01
    • 2012-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多