Micro ORM-维护SQL查询字符串

Micro ORM-维护SQL查询字符串,sql,orm,Sql,Orm,我不会详细说明为什么我在这个阶段探索使用Micro-ORM——只是说,当我使用一个成熟的ORM时,我感到无能为力。有太多的事情在后台自动发生,并不是所有这些都是最好的选择。我已经准备好返回原始数据库访问,但我发现了三个新成员:Dapper、PetaPoco和Massive。所以我决定用一个宠物项目来尝试低层次的方法。这不相关,但到目前为止,我正在使用PetaPoco 在任何情况下,我都很难决定如何维护我将从更高级别使用的SQL字符串。我可以想到三个主要的解决方案: 将SQL查询散布到我需要它们的

我不会详细说明为什么我在这个阶段探索使用Micro-ORM——只是说,当我使用一个成熟的ORM时,我感到无能为力。有太多的事情在后台自动发生,并不是所有这些都是最好的选择。我已经准备好返回原始数据库访问,但我发现了三个新成员:Dapper、PetaPoco和Massive。所以我决定用一个宠物项目来尝试低层次的方法。这不相关,但到目前为止,我正在使用PetaPoco

在任何情况下,我都很难决定如何维护我将从更高级别使用的SQL字符串。我可以想到三个主要的解决方案:

  • 将SQL查询散布到我需要它们的任何地方。这是基础设施最少的方法。然而,它在可维护性和可测试性方面都受到影响

  • 将查询使用限制为某些服务类。这有助于提高可维护性,但我需要实现的基础设施仍然不足。还可以构建这些服务类,这样就可以很容易地进行模拟以进行测试

  • 准备一些类,使系统具有一定的灵活性。我已经开始走这条路了。我实现了一个存储库接口和一个依赖于数据库的存储库类。我还构建了一些小接口来捕获可以传递到存储库的GetMany()方法的SQL查询。现在所有的查询都是作为单独的类实现的,我可能需要更多的接口来增加某种程度的数据库独立性——也许还需要在将查询修饰成分页和排序查询时具有一定的灵活性(同样,这也会使它们在处理不同的数据库时更加灵活)

  • 我现在主要担心的是,我已经进入了编写一个完整的ORM所需的所有函数的下滑阶段,但情况很糟糕。例如,我现在觉得编写或找到一个库来将linq调用转换为SQL语句是明智的,这样我就可以轻松地处理查询,或者编写扩展程序来修饰传递给它的任何查询,等等。但这是一项很大的任务,而且已经由大公司完成了,所以我抵制了去那里的冲动。我还希望通过显式地编写查询来保持对发送到数据库的查询的控制

    那么建议是什么呢?我应该选择第二个选项,还是尝试在第三个选项上步履蹒跚?我确信我不能不脸红地向任何人展示在第一个选项中编写的任何代码。有没有其他方法可以推荐


    编辑:在我问了这个问题之后,我意识到还有另一个选项,与这三个选项有些正交:存储过程。将所有查询作为存储过程放在数据库中似乎有一些好处。它们被保存在一个中心位置,不会在代码中传播(尽管维护是一个问题-参数可能会不同步)。对数据库方言的依赖是自动解决的:如果移动数据库,就可以移植所有存储过程,这样就完成了。还有安全方面的好处

    对于存储过程选项,备选方案1和2似乎更合适一些。似乎没有足够的实体来保证选项3,但仍然可以将过程调用命令与数据库访问代码分开

    我实现了选项3,没有存储过程,选项2有存储过程,似乎后者更适合我(以防有人对问题的结果感兴趣)

    我会说,将sql放在您将放置等效LINQ查询的位置,或者将sql放在DataContext.ExecuteQuery的位置。至于那在哪里。。。好吧,这取决于你,取决于你想要多少分离马克·格雷威尔,衣冠楚楚的创造者


    我认为关键的一点是,您不应该真正地重复使用SQL。如果您的逻辑被重复使用,那么它应该被包装在一个名为的方法中,然后可以从多个位置调用该方法。

    我知道您已经接受了您的答案,但我仍然想向您展示一个很好的替代方法,它可能对您的情况也有帮助。现在或将来

    使用存储过程时,明智的做法是使用T4 我倾向于在我的项目中使用存储过程,即使它没有使用PetaPoco、Dapper或Massive(项目在它们出现之前就开始了)。它使用BLToolkit。无论如何我没有编写方法来运行存储过程,也没有编写代码来提供存储过程参数,而是使用了一种为我生成代码的方法

    每当存储过程发生更改时(有些可能会被添加/删除,一些参数可能会被添加/删除/重命名/重新键入),我的代码在编译时就会中断,因为方法调用将不再与其签名匹配

    我将存储过程保存在一个文件中(这样它们就可以得到版本控制)。如果您在一个多开发人员团队中工作,最好将每个存储过程都放在自己的文件中。它使更新的痛苦大大减轻。我在一些项目中也经历过这种情况,只要SP的数量不是很大,它就可以正常工作。您可以根据与它们相关的实体将它们重组为文件夹

    无论如何。维护与存储过程有关,代码更改只需在Visual Studio中单击一个按钮即可立即转换所有T4。您不必搜索使用这些过程的方法。编译时会报告错误。有一件事不用担心

    因此,与其写作

    using (var db = new DbManager())
    {
        return db
            .SetSpCommand(
                "Person_SaveWithRelations",
                db.Parameter("@Name", name),
                db.Parameter("@Email", email),
                db.Parameter("@Birth", birth),
                db.Parameter("@ExternalID", exId))
            .ExecuteObject<Person>();
    }
    
    使用(var db=new DbManager())
    {
    返回数据库
    .SetSpCommand(
    “人脉关系”,
    db.参数(“@Name”,Name),
    db.参数(“@Email”,Email),
    db.参数(“@Birth”,Birth),
    db.参数(“@ExternalID”,exId))
    .ExecuteObject();
    }
    
    还有一堆杂志
    using (var db = new DataManager())
    {
        return db
            .Person
            .SaveWithRelations(name, email, birth, exId)
            .ExecuteObject<Person>();
    }