【问题标题】:Static vs. Instance Write Methods in Data Access Layer数据访问层中的静态与实例写入方法
【发布时间】:2012-04-29 08:54:51
【问题描述】:

我正在 C# 中为 SQL Server 数据库表创建数据访问层。数据访问层包含表中每一列的属性,以及从数据库读取和写入数据的方法。让读取方法基于实例似乎是有意义的。我的问题是关于处理数据库生成的主键属性 getter/setter 和 write 方法。据我所知,我有三个选择...

选项 1:使用静态方法同时只允许在主键上使用 getter 可以让我强制将所有正确的值写入数据库,但作为开发人员来说很笨拙。

选项 2:使用和基于实例的写入方法更易于维护,但我不确定如何处理主键上的 get/set,我可能必须先对实例进行某种验证写入数据库。

选项 3:别的东西,但我对 LINQ 和拖放东西很警惕,他们以前烧过我。

这里有标准做法吗?也许我只需要一个可靠教程的链接?

【问题讨论】:

  • 我用过的几个框架,会在你保存记录时根据数据库提供的内容自动更新主键。这让我完全不用担心主键。我也可以设置它,但可能会遇到数据库拒绝我设置主键的问题。您也可以将该属性保留为标准属性,但在您的 save() 或 update() 方法中,请确保忽略更新主键列 - 这对于开发人员来说会很奇怪,我宁愿看到类似 (您尝试设置主键,但数据库拒绝了您)

标签: c# asp.net data-access-layer


【解决方案1】:

您可能想阅读active record patterns 和其中的一些示例,然后实现您自己的类。

这是一个包含一些基本概念的简单类的粗略草图(如下)。

按照这种方法,您可以扩展该模式以满足您的需求。您可以从数据库中检索记录作为对象,更改其值,然后更新记录(选项 2)。或者如果开销太大,则使用直接更新数据库中记录的静态方法(选项1)。对于插入,如果需要,数据库(SP/查询)应验证表上的自然/唯一键,并可能返回指示唯一约束错误的特定值/代码)。对于更新,如果允许更新自然键字段,则需要执行相同的检查。

这在很大程度上取决于您的应用程序将为特定表允许哪些功能。

我倾向于从数据库中检索对象,然后更改值并保存,而不是静态方法。对我来说,调用代码更容易使用,并且可以更轻松地处理类内部的神秘业务逻辑。

public class MyEntityClass
{
    private int _isNew;
    private int _isDirty;
    private int _pkValue;
    private string _colValue;

    public MyEntityClass()
    {
        _isNew = true;
    }

    public int PKValue
    {
        get {return _pkValue;}
    }

    public string ColValue
    {
        get {return _colValue;}

        set
        {
            if (value != _colValue)
            {
                _colValue = value;
                _isDirty = true;
            }
        }
    }

    public void Load(int pkValue)
    {
        _pkValue = pkValue;

        //TODO: query database and set member vars based on results (_colVal)

        // if data found
        _isNew = false;
        _isDirty = false;
    }

    public void Save()
    {
        if (_isNew)
        {
            //TODO: insert record into DB
            //TODO: return DB generated PK ID value from SP/query, and set to _pkValue
        }
        else if (_isDirty)
        {
            //TODO: update record in DB
        }
    }
}

【讨论】:

    【解决方案2】:

    你看过Entity Framework。我知道你说过你对 LINQ 很谨慎,但 EF4 处理了你提到的很多事情,并且是 DAL 的相当标准的做法。

    【讨论】:

    • 我是个控制狂。我认为这种拖放功能和泄漏的抽象。我不能让 EF 在下面写一些疯狂的查询。不过还是谢谢。
    • @Ben 实体框架是由制作 c# 和 SQLServer 的同一个人制作的——它们旨在协同工作。 EF 非常可靠,作为概括,我可能会在我自己编写的 DAL 中比在 EF 中更快地发现一个错误。
    • 性能至上。实体框架使用两层对象映射,额外的映射具有性能成本,即使是简单的查询也比数据读取器慢 16 倍。另外,我认为它具有拖放功能,因此无法回答我的问题。
    • @Ben 你确定你没有过早优化吗?性能很重要,但是滚动你自己的 ORM,即使是小规模的,也可能比使用像 EF 或 nHibernate 这样的 ORM 花费的时间要长得多。 ORM 的性能会更差吗?你真的不知道,直到你尝试它并分析它。我已经将 nHibernate 用于多个应用程序,并且很少遇到关于它的执行方式或它生成的查询的问题。当它生成一个我想要手动调整的查询时,这很容易做到。
    【解决方案3】:

    我会坚持使用 ORM 工具(EF、Telerik 的 OpenAccess 等),除非您需要一个您需要(不想要)完全控制的自定义 dal。对于附带项目,我使用 ORM - 在工作中,但是我们有自己的自定义 DAL,其中包含提供者抽象以及对象和数据库之间的自定义映射。

    【讨论】:

      【解决方案4】:

      Nhibernate 也是一个非常可靠且经过验证的真正 ORM,有一个大型社区支持它。

      【讨论】:

        【解决方案5】:

        实体框架是您最初的 DAL 的方法,然后在您需要的地方进行优化:我们公司实际上在比较 EF 与 SQL 阅读器时做了一些基准测试,发现查询数据库以获取一两个表的信息价值,速度大约是 6 秒(两者都没有明显快于另一个)。在两张表之后,性能受到了影响,但并不是非常显着。编写自己的 SQL 语句变得有价值的一个地方是批量提交操作。此时 EF 允许您直接编写 SQL 查询。因此,请节省一些时间并使用 EF 进行基本的繁重工作,然后使用其直接连接进行更复杂的操作。 (两全其美)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-08-02
          • 1970-01-01
          • 1970-01-01
          • 2014-09-13
          • 2012-11-12
          • 2016-02-25
          • 2010-10-13
          • 2014-02-19
          相关资源
          最近更新 更多