C#:如何将我的工作单元代码包装在我的存储库类中

本文关键字:我的 存储 包装 代码 单元 我的工作 | 更新日期: 2023-09-27 18:34:15

请参阅我的存储库代码

public abstract class AdoRepository<T> where T : class
    {
        private static SqlConnection _connection;
        public AdoRepository(string connectionString)
        {
            _connection = new SqlConnection(connectionString);
        }
        public virtual T PopulateRecord(SqlDataReader reader)
        {
            return null;
        }
        public virtual void GetDataCount(int count)
        {
        }
        protected IEnumerable<T> GetRecords(SqlCommand command)
        {
            var list = new List<T>();
            command.Connection = _connection;
            _connection.Open();
            try
            {
                var reader = command.ExecuteReader();
                try
                {
                    while (reader.Read())
                    {
                        list.Add(PopulateRecord(reader));
                    }
                    reader.NextResult();
                    if (reader.HasRows)
                    {
                        while (reader.Read())
                        {
                            GetDataCount(Convert.ToInt32(reader["Count"].ToString()));
                        }
                    }
                }
                finally
                {
                    // Always call Close when done reading.
                    reader.Close();
                }
            }
            catch(Exception ex)
            {
                string Msg = ex.Message;
            }
            finally
            {
                _connection.Close();
            }
            return list;
        }
        protected T GetRecord(SqlCommand command)
        {
            T record = null;
            command.Connection = _connection;
            _connection.Open();
            try
            {
                var reader = command.ExecuteReader();
                try
                {
                    while (reader.Read())
                    {
                        record = PopulateRecord(reader);
                        break;
                    }
                }
                finally
                {
                    // Always call Close when done reading.
                    reader.Close();
                }
            }
            finally
            {
                _connection.Close();
            }
            return record;
        }
        protected IEnumerable<T> ExecuteStoredProc(SqlCommand command)
        {
            var list = new List<T>();
            command.Connection = _connection;
            command.CommandType = CommandType.StoredProcedure;
            _connection.Open();
            try
            {
                var reader = command.ExecuteReader();
                try
                {
                    while (reader.Read())
                    {
                        var record = PopulateRecord(reader);
                        if (record != null) list.Add(record);
                    }
                }
                finally
                {
                    // Always call Close when done reading.
                    reader.Close();
                }
            }
            finally
            {
                _connection.Close();
            }
            return list;
        }
    }
   public class StudentRepository : AdoRepository<Student>
    {
        public int DataCounter { get; set; }
        public StudentRepository(string connectionString)
            : base(connectionString)
        {
        }
        public IEnumerable<Student> GetAll()
        {
            // DBAs across the country are having strokes 
            //  over this next command!
            using (var command = new SqlCommand("SELECT ID, FirstName,LastName,IsActive,StateName,CityName FROM vwListStudents"))
            {
                return GetRecords(command);
            }
        }
        public Student GetById(string id)
        {
            // PARAMETERIZED QUERIES!
            using (var command = new SqlCommand("SELECT ID, FirstName,LastName,IsActive,StateName,CityName FROM vwListStudents WHERE Id = @id"))
            {
                command.Parameters.Add(new ObjectParameter("id", id));
                return GetRecord(command);
            }
        }
        public IEnumerable<Student> GetStudents(int StartIndex, int EndIndex, string sortCol, string sortOrder)
        {
            string strSQL = "SELECT * FROM vwListStudents WHERE ID >=" + StartIndex + " AND ID <=" + EndIndex;
            strSQL += " ORDER BY " + sortCol + " " + sortOrder;
            strSQL += ";SELECT COUNT(*) AS Count FROM vwListStudents";
            var command = new SqlCommand(strSQL);
            return GetRecords(command);
        }
        public override Student PopulateRecord(SqlDataReader reader)
        {
            return new Student
            {
                ID = Convert.ToInt32(reader["ID"].ToString()),
                FirstName = reader["FirstName"].ToString(),
                LastName = reader["LastName"].ToString(),
                IsActive = Convert.ToBoolean(reader["IsActive"]),
                StateName = reader["StateName"].ToString(),
                CityName = reader["CityName"].ToString()
            };
        }
        public override void GetDataCount(int count)
        {
            DataCounter = count;
        }
    }

这样添加工作单元代码

public class UnitOfWorkFactory
{
    public static IUnitOfWork Create()
    {
        var connection = new SqlConnection(ConfigurationManager.ConnectionStrings("MyDb").ConnectionString);
        connection.Open();
        return new AdoNetUnitOfWork(connection, true);
    }
}
public class AdoNetUnitOfWork : IUnitOfWork
{
    public AdoNetUnitOfWork(IDbConnection connection, bool ownsConnection)
    {
        _connection = connection;
        _ownsConnection=ownsConnection;
        _transaction = connection.BeginTransaction();
    }
    public IDbCommand CreateCommand()
    {
        var command = _connection.CreateCommand();
        command.Transaction = _transaction;
        return command;
    }
    public void SaveChanges()
    {
        if (_transaction == null)
            throw new InvalidOperationException("Transaction have already been commited. Check your transaction handling.");
        _transaction.Commit();
        _transaction = null;
    }
    public void Dispose()
    {
        if (_transaction != null)
        {
            _transaction.Rollback();
            _transaction = null;
        }
        if (_connection != null && _ownsConnection)
        {
            _connection.Close();
            _connection = null;
        }
    }
}
using (var uow = UnitOfWorkFactory.Create())
{
    var repos = new UserRepository(uow);
    uow.SaveChanges();
}
public class UserRepository
{
    private AdoNetUnitOfWork _unitOfWork;
    public UserRepository(IUnitOfWork uow)
    {
        if (uow == null)
            throw new ArgumentNullException("uow");
        _unitOfWork = uow as AdoNetUnitOfWork;
        if (_unitOfWork == null)
            throw new NotSupportedException("Ohh my, change that UnitOfWorkFactory, will you?");
    }
    public User Get(Guid id)
    {
        using (var cmd = _unitOfWork.CreateCommand())
        {
            cmd.CommandText = "SELECT * FROM Users WHERE Id = @id");
            cmd.AddParameter("id", id);
            // uses an extension method which I will demonstrate in a 
            // blog post in a couple of days
            return cmd.FirstOrDefault<User>();
        }
    }
}

但是我想在我的存储库类中添加工作单元代码。 可能属于AdoRepository类或StudentRepository类 因此,我不必一次又一次地编写以下代码。

using (var uow = UnitOfWorkFactory.Create())
{
    var repos = new UserRepository(uow);
    uow.SaveChanges();
}

因此,当我使用像UserRepository这样的任何存储库时,我必须一次又一次地重复这行代码UnitOfWorkFactory.Create()我不想要的,而是我正在寻找一种方法将工作单元代码嵌入到一些集中的地方,因此我可以减少重复的代码。

所以寻找想法和建议。 如果可能的话,给我修改后的代码版本。

谢谢

C#:如何将我的工作单元代码包装在我的存储库类中

我会直截了当:

包含存储库的 UoW 至少在涉及 DDD 的情况下是一种反模式。如果不是,那么您正在处理一个非常简单的应用程序,因此请让您的生活更轻松并使用实现您想要的 ORM。

作为经验法则,存储库可能包含 UoW 作为实现详细信息,您应该确定确实需要一个存储库。UoW 中的存储库是一个非常特殊的情况,它仅适用于 CRUD 应用程序,您只会重新发明 ORM 的一小部分。

直接使用 ado.net 是浪费时间(和金钱(。使用ORM或数据映射器(又名micro-ORM(。使用后一个选项,UoW 是 Db 事务。

使用 Ado.Net 您不会获得任何重要的东西,性能提升如此之小,甚至不好笑(我知道这一点,因为我已经对其进行了基准测试(。您唯一会得到的是更长的开发时间和人为错误。

实际上,如果我更好地看一下你的代码,你基本上是在构建一个微型ORM,而不知情。不过,它仍然不是一个存储库,因为抽象没有业务语义,并且它与实现细节过于紧密地耦合。