代码之家  ›  专栏  ›  技术社区  ›  Michael Maddox

您使用或建议什么DAL策略?

  •  7
  • Michael Maddox  · 技术社区  · 6 年前

    我的情况是我把事情搞砸了。我在1.5年前继承了我的代码库,当时我选择了这个位置,而不是重新设计车轮,尽管现在我知道我应该这样做,但我将DAL保持在与以前的开发人员几乎相同的结构中。

    实际上,有一个文件(现在是15K行代码)充当到一组DAO之间的过渡,这些DAO使用数据集和表适配器来检索数据。我的XSD文件已经发展到这样的大小,每次打开它都会导致R崩溃,而现在是15K行的中间类也需要R永远分析。更不用说它是丑陋的,它工作但不好,是调试的一个绝对的噩梦。

    到目前为止,我尝试的是改用NHibernate。NHibernate是一个很好的库,但不幸的是,它没有足够的适应性来使用我的应用程序,正如主要开发人员所说(Fabio Maulo),它几乎是我的应用程序需求和使用身份作为数据库pk策略时对NHibernate的限制的组合。

    所以现在我回到了设计我自己的DAL的基本上来。我正在为这个寻找一些不同的模式,但想得到您的DAL设计策略。以特定方式实施DAL有很多方法和原因,因此如果您能解释一下您的策略以及为什么它最适合您,我将非常感谢。

    事先谢谢!

    编辑:让我解释一下为什么NHibernate不起作用,因为这似乎是立即的反应。我的用户创建了一个“作业”,它实际上只是我作业类的一个短暂表示。在这个工作中,他们会给它一个或一个重量因素列表,这些因素在创建时也是暂时的。最后,他们提供了一个工作细节列表,其中有一个特定的权重因子与之相关。因为,在数据库中,当我去持久化作业时,权重因子是唯一的,当它找到重复的权重因子时,它会级联到权重因子中,从而死亡。根据Fabio的说法,我在将权重因子分配给细节之前尝试了运行一个检查(我不想这样做,因为我不想额外调用DB),但是在NH中调用CreateCriteria也会导致会话中的刷新,这会破坏我的缓存,从而杀死作业的整个内存表示。NH邮件列表的人说我应该切换到guid,但这不是一个可行的选择,因为转换过程将是一场噩梦。

    7 回复  |  直到 15 年前
        1
  •  1
  •   Chris McCall    15 年前

    我对NHibernate的经验是,虽然它有很多功能和非常高的性能,但您最终需要成为NHibernate专家才能解决一些意外的行为。通过阅读亲NHIBERNATE的答案并查看

    嗯,也许他用长跑 会话(每个业务会话 交易模型),在这种情况下 方法,使用身份是 气馁,因为它打破了你 工作单元(需要直接冲洗 插入新实体后)。一 解决方法可能是 身份,使用hilo身份 发电机。

    确切地说明了我的意思。

    我所做的是创建一个基本类,这个基本类在某种程度上是根据ActiveRecord模式建模的,我从继承的类继承并用将其附加到存储过程的属性标记继承的类,这些属性分别用于选择、插入、更新和删除。基类使用反射来读取属性并将类的属性值赋给sp参数,在select()的情况下,将结果sqldatareader的列值赋给泛型列表的属性。

    这就是dataObjectBase的外观:

    interface IDataObjectBase<T>
        {
            void Delete();
            void Insert();
            System.Collections.Generic.List<T> Select();
            void Update();
        }
    

    这是从中派生的数据类的一个示例:

    [StoredProcedure("usp_refund_CustRefundDetailInsert", OperationType.Insert)]
        [StoredProcedure("usp_refund_CustRefundDetailSelect", OperationType.Select)]
        [StoredProcedure("usp_refund_CustRefundDetailUpdate", OperationType.Update)]
        public class RefundDetail : DataObjectBase<RefundDetail>
        {
    
            [StoredProcedureParameter(null, OperationType.Update, ParameterDirection.Input)]
            [StoredProcedureParameter(null, OperationType.Insert, ParameterDirection.Output)]
            [StoredProcedureParameter(null, OperationType.Select, ParameterDirection.Input)]
            [ResultColumn(null)]
            public int? RefundDetailId
            { get; set; }
    
            [StoredProcedureParameter(null, OperationType.Update, ParameterDirection.Input)]
            [StoredProcedureParameter(null, OperationType.Insert, ParameterDirection.Input)]
            [StoredProcedureParameter(null, OperationType.Select, ParameterDirection.Input)]
            [ResultColumn(null)]
            public int? RefundId
            { get; set; }
            [StoredProcedureParameter(null, OperationType.Update, ParameterDirection.Input)]
            [StoredProcedureParameter(null, OperationType.Insert, ParameterDirection.Input)]
            [ResultColumn(null)]
            public int RefundTypeId
            { get; set; }
    
            [StoredProcedureParameter(null, OperationType.Update, ParameterDirection.Input)]
            [StoredProcedureParameter(null, OperationType.Insert, ParameterDirection.Input)]
            [ResultColumn(null)]
            public decimal? RefundAmount
            { get; set; }        
            [StoredProcedureParameter(null, OperationType.Update, ParameterDirection.Input)]
            [StoredProcedureParameter(null, OperationType.Insert, ParameterDirection.Input)]
            [ResultColumn(null)]
            public string ARTranId
            { get; set; }
    
        }
    

    我知道我似乎在重新设计方向盘,但我发现的所有库要么过于依赖其他库(例如ActiveRecord+NHibernate,这是一个很接近的秒),要么过于复杂,无法使用和管理。

    我制作的库非常轻(可能有几百行c),除了为参数赋值和执行sp之外,它什么也不做。它还可以很好地生成代码,所以最终我希望不会编写数据访问代码。我还喜欢它使用一个类实例而不是静态类,这样我就可以将数据传递给查询,而不必使用一些笨拙的条件集合或HQL。select()的意思是“变得更像我”。

        2
  •  1
  •   Otávio Décio    15 年前

    对我来说,最适合的是一个非常简单的概念——使用DAO类定义和反射创建填充和保存它们所需的所有SQL。这样就没有映射文件,只有简单的类。我的DAO需要一个实体基类,所以它不是POCO,但这并不困扰我。它支持任何类型的主键,无论是单标识列还是多列。

        3
  •  0
  •   Matthew Groves    15 年前

    如果您的DAL被写到一个接口上,那么切换到nhibernate或其他可编译的东西会容易得多(我更喜欢流利的nhibernate,但是我离题了)。那么,为什么不花时间重构DAL以使用接口,然后使用NH或您选择的ORM编写新的实现呢?

        4
  •  0
  •   Shiraz Bhaiji    15 年前

    在最近的项目中,我们已经停止编写单独的DAL。

    相反,我们使用对象关系映射器(在我们的实例实体框架中)。然后,我们让业务层直接针对ORM进行编程。

    在某些情况下,这节省了我们90%以上的开发工作。

        5
  •  0
  •   RichardOD    15 年前

    我的第一步是破解一个15克洛克怪物的密码,然后制定一个新的DAL策略。

        6
  •  0
  •   Steve    15 年前

    如果您使用的是SQL Server,那么linq to sql就很好了。linqtosql提供程序可以访问和mysql。不过我还没有测试过。LinqToSQL遵循UnitOfWork模型,该模型类似于ADO.NET函数。对数据的本地副本进行一系列更改,然后用一个更新调用提交所有更改。我觉得很干净。

    您还可以自己扩展DataRow类,以提供对字段的强类型访问。我使用XSLT根据每个表的元数据生成数据行后代。我有一个通用的数据表decendant。mydataTable,其中t是派生行。我知道MS的强类型数据集也有类似的功能,但我想要一个我完全控制的轻量级通用版本。一旦有了这个,就可以编写静态访问方法来查询数据库并填充数据表。

    您将负责将数据表中的更改写回数据源。我将编写一个通用类或方法来创建更新、插入和删除。

    祝你好运!

        7
  •  0
  •   pocheptsov    15 年前

    我使用SPs的MineWrapper进行最快的数据检索,并在性能不是目标时使用L2s。我的DAL使用存储库模式和TDD的封装逻辑。