3

这更多是一个设计问题。

我正在构建一个应用程序,并且我创建了我的存储库模式结构,如下所示:

我的核心名称空间是 DAL/Repository/BusinessLogic 层程序集。

顺便说一句,我使用 Dapper.NET micro ORM 作为我的数据连接,这就是为什么你会在我的 SqlConnection 对象上看到一个扩展。

对于我的数据访问,我创建了一个基础存储库类:

namespace Core
{
    public class BaseRepository<T>: IDisposable where T : BaseEntity 
    {
        protected SqlConnection conn = null;


        #region Constructors
        public BaseRepository() : this("LOCAL")
        {

        }

        public BaseRepository(string configurationKey = "LOCAL")
        {
            conn = new SqlConnection(ConfigurationManager.ConnectionStrings[configurationKey].ConnectionString);
        }
        #endregion

        #region IDisposable
        public void Dispose()
        {
            conn.Dispose();
        }
        #endregion


        /// <summary>
        /// returns a list of entities
        /// </summary>
        /// <typeparam name="T">BaseEntity type</typeparam>
        /// <param name="sproc">optional parameters, stored procedure name.</param>
        /// <returns>BaseEntity</returns>
        protected virtual IEnumerable<T> GetListEntity(string sproc = null)
        {
            string storedProcName = string.Empty;
            if (sproc == null)
            {
                storedProcName = "[dbo].sp_GetList_" + typeof(T).ToString().Replace("Core.",string.Empty);
            }
            else
            {
                storedProcName = sproc;
            }

            IEnumerable<T> items = new List<T>();
            try
            {
                conn.Open();
                items = conn.Query<T>(storedProcName,
                                                     commandType: CommandType.StoredProcedure);
                conn.Close();
            }
            finally
            {
                conn.Close();
            }


            return items;
        }


    }
}

对于我拥有的每个实体,可以说 ExtendedUser, Messages ,我正在像这样在 Interface-Class 对上创建它:

namespace Core
{
    public class ExtendedUserRepository : BaseRepository<UsersExtended>,IExtendedUserRepository
    {

        public ExtendedUserRepository() : this("PROD") 
        {
        }

        public ExtendedUserRepository(string configurationKey) : base(configurationKey)
        {
        }


        public UsersExtended GetExtendedUser(string username)
        {
            var list = GetListEntity().SingleOrDefault(u => u.Username == username);
            return list;
        }

        public UsersExtended GetExtendedUser(Guid userid)
        {
            throw new NotImplementedException();
        }


        public List<UsersExtended> GetListExtendedUser()
        {
            throw new NotImplementedException();
        }
    }
}

等等

上面的代码只是实体之一:ExtendedUser。

问题是:我应该为我拥有的每个实体创建一个 Interface-ClassThatImplemenetsInterface 对吗?或者我应该只有一个 RepositoryClass 和一个 IRepository 接口,其中包含来自我所有实体的所有方法?

4

2 回答 2

1

我认为您不需要无缘无故地创建界面。我什至不明白为什么在这里需要基础存储库类。我什至认为这不是存储库而是 DAL(数据访问层),但这是定义争论。

我认为良好的 DAL 实现应该将数据库结构与业务逻辑结构解耦 - 但硬编码 sp_GetList_XXXEntityNameXXX 模式或在 DAL 之外传递存储过程名称并不是解耦。

如果您认为所有实体列表都是通过一种方式获取的,那么您非常乐观或者您的应用程序非常简单,并且您将始终需要业务逻辑中的全套实体而无需任何参数。

仅当您计划替换/包装不同的实现或在一个类中混合几个接口时才需要将接口与实现分离。否则不需要。

创建存储库时不要考虑实体。存储库包含业务逻辑,应该构建在使用场景之上。拥有像你这样的类更多的是关于数据访问层 - DAL 是建立在你在业务逻辑中需要的查询之上的。可能您永远不会一次需要所有用户的列表 - 但经常需要活动用户、特权用户等的列表。

很难预测您将需要哪些查询 - 所以我更喜欢从业务逻辑开始设计并顺便添加 DAL 方法。

于 2012-08-31T19:42:43.197 回答
1

具有复杂域模型的系统通常受益于一层,例如 Data Mapper (165) 提供的层,该层将域对象与数据库访问代码的细节隔离开来。在这样的系统中,在查询构造代码集中的映射层之上构建另一个抽象层是值得的。

http://martinfowler.com/eaaCatalog/repository.html

使用通用存储库,您可以使用常用方法,如、findBy(array('id' => 1))findOneBy(array('email' => 'john@bar.com'))等。事实上,它将只有一个界面。findById()findAll()

您将始终必须创建一个具体的实现,该实现将指示哪个是将由存储库管理的域对象以完成此操作getUsersRepository().findAll()

此外,如果您需要更复杂的查询,您可以在具体实现上创建新方法,例如findMostActiveUsers()然后在您的应用程序中重用它。

现在,回答你的问题:

您的应用程序将期望至少有一个接口(通用接口,具有通用方法)。但是如果你设法拥有特定的方法,就像我刚才提到的那样,你最好拥有另一个接口(例如RepositoryInterface 和UsersRepositoryInteface)。

考虑到这一点,您将只依赖存储库接口。查询构造将被具体实现封装。因此,您将能够更改您的存储库实现(例如使用完整的 ORM),而不会影响应用程序的其余部分。

于 2012-08-31T21:54:40.217 回答