活动记录设计模式?

Jon*_*Jon 5 database oop orm design-patterns

我最近一直在研究各种 ORM 框架(主要是 .net),发现 Active Record 设计模式通常用于持久化数据。

我只是想知道每个人对活动记录模式的看法是什么?我个人认为它对数据对象承担了太多的责任,无论它只是一个数据容器还是一个实体 bean。我总是从一个中央控制器接近持久化对象,该控制器公开了一个方法,例如 Persist(),它接受一个接口,比如 IEntityBean,而不是让 bean 将它的持久性排序出来。这也是我为填充所采用的方法我获取一个数据集并一般填充 bean,而不是让 bean 接收数据集并填充自身。我只是不喜欢有逻辑的豆子。这是一种老式的方法还是其他人也有我的恐惧?

不使用活动记录模式映射表到对象和对象到表的 ORM 框架如何?控制持久化的中央控制器是一种糟糕的方法吗?

提前感谢您的意见!

thi*_*eek 4

我不使用 ActiveRecord,因为ActiveRecord 严重违反了 SRP。我们有自己的内部定制 ORM。

编辑

在我们的 ORM 中,我们大量利用了 C# 3.0 的功能。我们有一个名为的库项目Application.Infrastructure,它托管我们业务对象的所有基类。我们有一个验证框架和使用属性的自动映射。

ORM 大量使用属性来自动执行大多数繁琐的任务,例如映射和验证。我可以添加新功能作为框架中的新方面。

TableMapping属性会让我们知道该对象映射到哪个表。该DataFieldMapping属性会让我们知道 object 对象的属性映射到哪一列。这validation framework让我可以在指定的帮助下验证每个字段ValidationAttribute

每个业务对象都有一个基类EntityBase,业务集合有EntityCollectionBase。我们使用传统的数据集进行数据库交互,并且我们为EntityBase、EntityCollectionBase、DataRow和DataTable编写了扩展方法。此扩展方法将从对象的属性中读取映射元数据,并通过反射执行[双向]映射。

在我的应用程序中,示例业务对象将如下所示。

用户.cs

[TableMapping("Users")]
public class User : EntityBase
{
    #region Constructor(s)
    public AppUser()
    {
        BookCollection = new BookCollection();
    }
    #endregion

    #region Properties

    #region Default Properties - Direct Field Mapping using DataFieldMappingAttribute

    private System.Int32 _UserId;

    private System.String _FirstName;
    private System.String _LastName;
    private System.String _UserName;
    private System.Boolean _IsActive;

    [DataFieldMapping("UserID")]
    [DataObjectFieldAttribute(true, true, false)]
    [NotNullOrEmpty(Message = "UserID From Users Table Is Required.")]
    public override int Id
    {
        get
        {
            return _UserId;
        }
        set
        {
            _UserId = value;
        }
    }

    [DataFieldMapping("UserName")]
    [Searchable]
    [NotNullOrEmpty(Message = "Username Is Required.")]
    public string UserName
    {
        get
        {
            return _UserName;
        }
        set
        {
            _UserName = value;
        }
    }

    [DataFieldMapping("FirstName")]
    [Searchable]
    public string FirstName
    {
        get
        {
            return _FirstName;
        }
        set
        {
            _FirstName = value;
        }
    }

    [DataFieldMapping("LastName")]
    [Searchable]
    public string LastName
    {
        get
        {
            return _LastName;
        }
        set
        {
            _LastName = value;
        }
    }

    [DataFieldMapping("IsActive")]
    public bool IsActive
    {
        get
        {
            return _IsActive;
        }
        set
        {
            _IsActive = value;
        }
    }

    #region One-To-Many Mappings
    public BookCollection Books { get; set; }

    #endregion

    #region Derived Properties
    public string FullName { get { return this.FirstName + " " + this.LastName; } }

    #endregion

    #endregion

    public override bool Validate()
    {
        bool baseValid = base.Validate();
        bool localValid = Books.Validate();
        return baseValid && localValid;
    }
}
Run Code Online (Sandbox Code Playgroud)

BookCollection.cs

/// <summary>
/// The BookCollection class is designed to work with lists of instances of Book.
/// </summary>
public class BookCollection : EntityCollectionBase<Book>
{
    /// <summary>
    /// Initializes a new instance of the BookCollection class.
    /// </summary>
    public BookCollection()
    {
    }

    /// <summary>
    /// Initializes a new instance of the BookCollection class.
    /// </summary>
    public BookCollection (IList<Book> initialList)
        : base(initialList)
    {
    }
}
Run Code Online (Sandbox Code Playgroud)