【问题标题】:.NET service that handles import and export (integration)处理导入和导出(集成)的 .NET 服务
【发布时间】:2014-02-03 00:09:04
【问题描述】:

我一直在谷歌上搜索有关构建集成引擎时设计模式的一些技巧。

我有一个 SQL Server 来保存我想要导出的所有数据(这也是我将插入我导入的数据的地方)。我有一项服务可以根据时间间隔等执行命令。虽然我真正纠结的一件事是在软件中处理数据处理的方式。

例如,在我制作的导出程序中,我有一个类似的结构

// Entity order
public class Order {
    int OrderID { get; set; }
    string OrderNo { get; set; }

    // One order can include loads of registrations
    // A registration can only have a reference to one order
    // Basically a mirror of the database
    List<Registration> RegistrationList { get; set; }
}

// Entity registration
public class Registration {
    int RegistrationID { get; set; }
    string Name { get; set; }
    // Some more variables
}

// Controller(?) 
public class OrderController : IControlOrder
{
    private IControlRegistrations _registrationController;
    public OrderController()
    {
        this._registrationController = new RegistrationController();
    }

    public List<Order> get() {
        List<Order> orderList = new List<Order>();
        // Query database
        foreach(...) {
            // Short example
            Order order = new Order();
            order.OrderNo = ...
            order.OrderID = ...
            order.RegistrationList = _registrationController.getRegistrationsBasedOnOrder(order);
        }
        // Iterate through every row
        // Create a new Order-object per iterate
        return orderList;
    }

    public void updateOrder(Order order) {
        // Update the order in the database (set exported-flag)
    }
}

public RegistrationController : IControlRegistrations
{
    public List<Registration> getRegistrationsBasedOnOrder(Order order)
    {
        List<Registration> list = new List<Registration>();
        // Query DB based on OrderID

        return list;
    }

    public void update(Registration registration)
    {
        // Update the registration in the database
    }
}

// Output
public class Output 
{
    private IControlOrder _controller;
    public Output(IControlOrder controller)
    {
        this._controller = controller;
    }

    public void export()
    {
        // Build XML
        // ... Example
        //
        //<Orders>
        //   <Order>
        //      <OrderNo>KF322</OrderNo>
        //      <RegistrationList>
        //         <!-- All the registrations with a reference to this order -->   
        //      </RegistrationList>   
        //   </Order>
        //   <Order>
        //      <OrderNo>KF323</OrderNo>
        //      <RegistrationList>
        //         <!-- All the registrations with a reference to this order -->   
        //      </RegistrationList> 
        //   </Order>
        //</Orders>


        foreach(Order order in _controller.get())
        {
             // Create the order info in the XML, then create registrations
             foreach(Registration reg in order.RegistrationList)
             {
                 // Create the registration list in the XML
             }     
        }
        // Save the file to a network drive.
    }
}

我很确定我违反了设计模式的每一条规则。最终我的代码变得杂乱无章,每一层的责任(不确定我是否可以称之为层)变得一团糟。例如,如果订单还与描述和地址存在一对多关系,OrderController 类会变得非常混乱。在我的下一个项目中,我还将实施导入,我不仅会导出订单,还会导出其他类似的主数据。所以我相信我必须精通接口、帮助类等。在输出文件或将其插入数据库之前,我还必须验证从数据库和集成程序中检索到的所有数据。

你们中是否有人知道集成引擎的良好设计模式(只是一个可遵循的理论)?这个问题可能没有建设性,但是当程序要大几十倍时,我使用的小房子设计是不够的。

非常感谢任何帮助 :) 谢谢!

【问题讨论】:

    标签: c# .net sql-server design-patterns integration


    【解决方案1】:

    您可能想了解一下 Command-Query Segregation。基本上这归结为几个概念:

    • 用于写入的命令,用于读取的查询。通过命令导入,通过查询导出。
    • 单个命令/查询仅处理一种类型的导入/导出

    因此,要从用户那里保存数据,您将在控制器中获取文件/数据并将其传递给处理此类数据的命令。对于导出,您在控制器中执行查询,查询将从数据库中提取数据并适当地格式化。

    有时,如果您将数据提取为 XLS 或其他格式,您可能需要引入单独的渲染器。这样你的关注点就分开了——查询只提取数据,渲染器将该数据转换为所需的格式。这样,您只需添加新的渲染器即可将数据提取为不同的格式。

    命令也是如此——命令的一部分可以是解析器,将传入的数据解析为类实例,然后命令将其保存到数据库中。

    您可以在此处查看示例和更多 CQRS 详细信息:

    【讨论】:

    • 我明天去看看!听起来像是定义职责的好方法,而且它也可能使代码更易于理解!非常感谢:)
    • 没问题。我们已经使用了服务和全方位的功能类,但是当你超过 30 个控制器时,事情就会变得一团糟。搬到 CQRS 之后 - 一切都清楚了:课堂只做一件事和一件事。您可以查看我使用 CQRS github.com/trailmax/Amv.Reporting 的小应用程序,但对于 DB,我使用 Raven DB,而不是 EF
    【解决方案2】:

    这看起来还不错。有两个命名问题,特别是您的控制器不是控制器,而是 repositories 并且您的输出类是 service(这样OutputService 会是一个更好的名称)。 p>

    分层没问题。你有一个很深的领域模型。然后你在上层有存储库,在它上面你有你的服务。如果您遵循简单的约定,其中存储库类名称以Repository (OrderRepository) 和服务以..Service 结尾,并且您将每一层放在单独的程序集中并允许上层程序集仅引用下层程序集,那么您将清理你的很多困惑。

    我的想法是不要手动编写模型类和存储库。这没有多大意义,因为有很多陷阱。相反,首先使用 Entity Framework 逆向工程代码选项从数据库中对您的模型进行逆向工程,然后使用 Entity Framework 代替手动创建存储库。唯一需要手动创建的层就是实现特定业务流程的服务层。

    【讨论】:

    • 只要更改术语之类的“次要细节”,它就更有意义了,这真是太酷了。 EF有点让我困惑,因为它对我来说就像一个魔术盒,可能是因为我自己没有使用过它,只是看到了一些使用它的生产代码。想到的另一件事是验证我插入到模型中的模型数据。但是我相信我会在某个时候解决这个问题:) 这个设计模型有什么具体的名称吗?也感谢您的帮助,只需更改术语即可理解!
    • 很抱歉再次打扰您,我已决定使用您提供的命名约定采用这种模式。如果我以上面为例,我想创建两个输出,前面提到的 XML 和一个 Web 服务连接,以及一个报告(我真正导出了什么)。 IOutputService 是否应该是具有已定义报告方法和抽象导出方法的抽象类?您针对该特定目的建议什么设计? :)
    • @Alex07:听起来像是一个很好的、独立的代码审查问题codereview.stackexchange.com
    猜你喜欢
    • 1970-01-01
    • 2014-03-04
    • 2023-03-14
    • 1970-01-01
    • 2014-08-12
    • 2011-03-10
    • 2012-06-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多