代码之家  ›  专栏  ›  技术社区  ›  seth

我的查询类。你的意见?

  •  6
  • seth  · 技术社区  · 5 年前

    我只想分享这个查询类,让你对它有个想法。查询类帮助对数据库连接执行查询。我还没有包括实现,发布的内容有点多。下面是一个示例调用,您将得到以下想法:

    OrdersDataTable table = 
       new Query(connection)
       .Table("Orders")
       .Fields("OrderID,CustomerID,Description,Amount")
       .GreaterThan("OrderID", 1000)
       .OrderBy("OrderID")
       .Execute<OrdersDataTable>();
    

    我喜欢这门课的原因如下:

    • 不需要编写ADO.NET命令代码。调用这个类所占用的行数比ADO.NET的同类少。
    • 每个成员函数都返回这个值,这样可以将多个调用链接在一起。我不确定这个图案是否有名字。你知道吗?
    • 处理mysql、oledb和sqlserver方言。
    • 对我来说似乎比ADO.NET的要求更具可读性。
    • 通话顺序无关紧要。在内部集合中缓冲所有参数,并在调用Execute时读取。
    • 我的场景要求我与多个数据库产品通信,因此我希望以通用的方式编写一次查询,并只传入给定的连接。利用数据库特定的特性(如存储过程)会很困难。

    我有一个内部使用这个类的DAL。用户界面会调用DAL,传递一些查询参数,然后返回数据表。该类确实帮助减少了loc的dal实现,并使其更具可读性。

    以下是DAL调用示例:

    OrdersDataTable orders = Orders.GetByOrderId( 1 )
    

    IMPL:

    public static OrdersDataTable GetByOrderId( int id )
    {
        return  
           new Query(connection)
           .Table("Orders")
           .Fields("OrderID,CustomerID,Description,Amount")
           .Equals("OrderID", id)
           .Execute<OrdersDataTable>();
    }
    

    谢谢!

    编辑:感谢大家的反馈。你们中的许多人建议使用linqtosql。我没有选择Linq,因为Microsoft目前只支持SQL Server。我需要查询jet、mysql和sql-server表。

    有人问如何构造和或子句。这里有一个例子

    //and example
        public static OrdersDataTable GetByOrderIdAndCustomerId( int orderId, int customerId )
        {
            return  
               new Query(connection)
               .Table("Orders")
               .Fields("OrderID,CustomerID,Description,Amount")
               .Equals("OrderID", orderId)
               .Equals("CustomerID", customerId)
               .Execute<OrdersDataTable>();
        }
    
    //or example
        public static OrdersDataTable GetByOrderIdOrCustomerId( int orderId, int customerId )
        {
            return  
               new Query(connection)
               .Table("Orders")
               .Fields("OrderID,CustomerID,Description,Amount")
               .OrBegin
               .Equals("OrderID", orderId)
               .Equals("CustomerID", customerId)
               .OrEnd
               .Execute<OrdersDataTable>();
        }
    
    4 回复  |  直到 15 年前
        1
  •  3
  •   Chris Marisic    15 年前

    看起来您已经编写了一个非常好的小ORM(对象关系映射器),其中包含存储库(或接近)模式的实现。您还利用了名为fluent interfaces的设计模式,它允许您进行.table.fields相互层叠。

    所有这三种模式都很好地包含在现代软件系统设计中,因为您已经注意到它们大大减少了loc,增强了可维护性,并大大提高了测试能力。我还喜欢您构造的功能能够正确地使用泛型返回强类型对象。

    编辑: 我能看到的唯一可能改进的地方是更改每个调用都是一个新查询的事实,并且可能更改您的代码以使用依赖项注入框架,该框架将注入正确的提供程序,并且当调用对象时,它将为查询启动一个数据库事务。如果您的代码在查询类内部已经做了很多可以称为“穷人的依赖注入”的工作,或者至少是非常相似的(取决于您的实现),如果它已经为您工作了,并且您不打算真正扩展您的数据库支持类型,那么穷人的DI应该很好。我不再是任何使用中新关键字的粉丝,因为它通常会导致DI框架减轻代码耦合的高度(或者是用于方法隐藏的是一个糟糕的设计决策)。

    回应马克的回答 ,我通常不喜欢代码生成,它似乎总是成为一个失败点,但是他确实有一个非常好的点来减少所涉及的魔法字符串的数量。不过,我会选择使用lambda运算符和表达式来处理这个问题,这样您就可以实现:

    public static OrdersDataTable GetByOrderId( int id )
    {
        return  
           new Query(connection)
           .Table(x => Inflector.Pluralize(x.GetType())
           .Fields(x=> { x.OrderID, x.CustomerID, x.Description, x.Amount })
           .Equals(x=>x.OrderID, id)
           .Execute<OrdersDataTable>();
    }
    

    这将消除所有神奇字符串重构问题,使您能够更容易地利用Microsoft内置的重构工具或Resharper(当然,Resharper可以在重构期间找到神奇字符串)。

    inflector是一个免费的库(不记得它是不是OSS),它包含了处理文本的功能,复数方法将取一个词并使其…如果你猜不出来,就用复数。当你有类似的故事时,这是有用的,因为故事不正确,而且inflector会正确地返回你的“故事”,所以你不能只去gettype()+“s”。

        2
  •  1
  •   mkchandler    15 年前

    我通常试着远离这些功能性的做事方式。有时,当问题出现时,跟踪问题会令人困惑。

    我只需要使用LINQ,用更可读的代码完成相同的任务。

        3
  •  0
  •   Mark Redman    15 年前

    尽管我同意Linq的设计是为了实现这一点,但如果它能满足您的需求,就没有理由不构建您自己的架构。

    我会更进一步,使用代码生成来构建枚举类型或其他基于对象的实体,以减少对文本的需求。(减少打字错误)

        4
  •  0
  •   Chris Stewart    15 年前

    这是一个有趣的练习,您的代码看起来非常易读和简洁。在一个生产环境中,我可能会远离重新发明轮子,除非有一个严重的需要。我和你的时间,最好是在应用程序中创造价值,而不是在自定义ORM中添加功能,我们可以在其他经过战斗测试的软件包(如LINQ和NHibernate)中“免费”获得这些功能。