我应该如何封装数据库访问权限?


10

有哪些用于管理数据库访问的良好类结构的示例?我是类封装的迷,并且希望容器(例如car)不执行数据库任务。

我还希望将来能够轻松放入数据库缓存之类的功能。

我经常采用容器类的模式,并结合使用getter和setter来进行验证和由单个singleton类执行的数据库访问。话虽这么说,这常常在两者之间混在一起并且变得非常混乱。

对不起,如果我的问题很难理解;我对数据库的术语不是绝对确定。如果需要,请随时要求澄清。


您是否考虑过使用ORM将类链接到数据库,例如Wt :: Dbo
user52875 '07年

Answers:


11

我更喜欢使用存储库模式来封装数据访问。简而言之,存储库负责加载特定对象所需的所有数据。像您的示例一样,假设您有一个Car对象。但是汽车的所有属性,品牌,型号,年份,所有者,功能(CD播放器,4WD等)都存储在整个数据库的各个表中。存储库确定如何加载和保存数据。如果需要多个较小的查询,可以,但是只有存储库模式需要知道这一点。调用存储库的服务层仅需要知道要调用哪个存储库。

然后可以将其与工作模式组合。因此,在您的示例中,服务层会说它需要加载汽车实体,它具有某种唯一标识符,然后将该标识符向下发送到存储库。存储库返回汽车实体。其他一些代码操纵汽车实体,然后将该实体发送回存储库,以便可以将其保存。

如果您真的想全力以赴,那么存储库层将只公开接口,例如ICarRepository。该存储库将包含一个工厂,服务层将使用该工厂来获取ICarRepository接口。所有数据库访问都将隐藏在界面的后面,这使单元测试变得更加容易。


除了关于c ++中不存在的接口的最后一点之外,其他所有内容都很好(除非OP并非要标记c ++)。我很想看到C ++中的存储库模式实现,因为我想将其与QT一起使用。我很惊讶网上没有什么可用的= [
johnildergleidisson

6

我已经使用了策略模式来封装数据访问。通过此模式,您可以在通用界面后隐藏正在使用的存储类型。在界面中,在不考虑存储类型(文件,数据库,Web)的情况下定义数据访问方法。然后,对于当前的存储选择,在实现策略接口的类中,实现数据访问详细信息。这样,您的应用程序就不会在乎您使用的数据源。

您还可以构建一个服务层,该服务层使用当前的数据存储策略实例来定义更多特定于应用程序的细节,而不是将数据访问和业务逻辑混合在一起。


那么,您将为每种类型添加一个访问类还是为所有类型添加一个大类?
Will03uk 2012年

我个人也将考虑对从野外到我的服务器/应用程序的每个数据采用显式强制转换。
user827992 '07年

+1我喜欢这种模式的外观,但是(在我的项目范围内)我感到很难为数据库单独管理每种算法;尽管我肯定会在其他应用程序中使用它。Lambda必须很好地补充这一点。
Will03uk

1

这是数据库工厂模式的示例;

using System.Reflection;
using System.Configuration;

public sealed class DatabaseFactory
{
    public static DatabaseFactorySectionHandler sectionHandler = (DatabaseFactorySectionHandler)ConfigurationManager.GetSection("DatabaseFactoryConfiguration");

    private DatabaseFactory() { }

    public static Database CreateDatabase()
    {
        // Verify a DatabaseFactoryConfiguration line exists in the web.config.
        if (sectionHandler.Name.Length == 0)
        {
            throw new Exception("Database name not defined in DatabaseFactoryConfiguration section of web.config.");
        }

        try
        {
            // Find the class
            Type database = Type.GetType(sectionHandler.Name);

            // Get it's constructor
            ConstructorInfo constructor = database.GetConstructor(new Type[] { });

            // Invoke it's constructor, which returns an instance.
            Database createdObject = (Database)constructor.Invoke(null);

            // Initialize the connection string property for the database.
            createdObject.connectionString = sectionHandler.ConnectionString;

            // Pass back the instance as a Database
            return createdObject;
        }
        catch (Exception excep)
        {
            throw new Exception("Error instantiating database " + sectionHandler.Name + ". " + excep.Message);
        }
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.