65.9K
CodeProject 正在变化。 阅读更多。
Home

管理您的CRUD操作

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.90/5 (16投票s)

2013年5月16日

CPOL

2分钟阅读

viewsIcon

38473

本文将帮助您更高效地管理CRUD操作

介绍  

在这里,我将向您展示如何以更有效的方式管理我们的 CRUD 操作。 我们经常在日常工作中用到这个。 但是一些代码可能会写得不必要。 这是冗余代码。 我的方法是指出现这些冗余代码并消除冗余。

使用代码

在我自己的类上执行 Select 操作的典型代码。

  public class Employee
    {
        DataSet ds = new DataSet();
 
        public DataSet SelectEmployee()
        {
            string mySelectQuery = "SELECT ID,Name,Address FROM Employee ";
            var myConnString = ConfigurationManager.ConnectionStrings["conProduction"].ToString();
            SqlConnection myConnection = new SqlConnection(myConnString);
            SqlCommand myCommand = new SqlCommand(mySelectQuery, myConnection);
            myConnection.Open();
            var adapter = new SqlDataAdapter(myCommand);
            adapter.Fill(ds);
            myConnection.Close();
            return ds;
        }
    } 

我认为大多数人都熟悉这种类型。 这里我的类 Employee 必须执行所有步骤才能成功执行查询。 然后再次对于 insert update or delete,它将经历所有步骤,例如获取 Connectionstring, SqlCommand, ExecuteQuery 等。 如果添加了另一个新类,它也会遵循创建所有这些对象的开销。 这将只是浪费时间并使代码变得冗余,对吧? 好的,现在我将向您展示一些不同的机制来处理这种情况。

现在我将分离 connectioncommand 的职责。

 public interface IConnection
    {
        SqlConnection Connection { get;}
    }
  public interface ICommand
    {
        string CommandText  // For Inline Sql
        { get; set; }
        string SpName 
        { get; set; }
        List<SqlParameter> SqlParams { get; set; }
        bool Execute();
        DataSet SelectData();
    }
如果你仔细观察,你会发现这些是我们执行命令所需要的常见的东西。 现在我们有了通用的结构,所以现在我们需要一些人来实现它并承担责任。 为了做到这一点,我们必须创建实现 IConnection 和 ICommand 的类。
 public class ConnectionManager : IConnection
    {
        private string GetConnectionString()
        {
            string connectionString = string.Empty;
            var connection = ConfigurationManager
                          .ConnectionStrings
                          .Cast<ConnectionStringSettings>()
                          .Where(p => p.LockItem == false).FirstOrDefault();
 
            connectionString = connection != null ? connection.ConnectionString : string.Empty;
            return connectionString;
        }
 
 
        private SqlConnection GetConnection()
        {
            return new SqlConnection(GetConnectionString());
        }
 
        public SqlConnection Connection
        {
            get
            {
                return GetConnection();
            }
 
        }
 

这是连接管理器类。 这里 private string GetConnectionString() 方法根据 web.config Connectionstring LockItem 属性给出连接字符串。 看下面的图片。

图 1.1 

因此,具有 lockItem=false 的连接字符串将用作当前连接。 因此,在将其部署到相应的服务器后,我们需要将属性设置为 false,其余的必须为 true (锁定)。 我们的 readonly 属性 Connection 根据 web.config 配置获取数据。 对于 IConnection,它是 ConnectionManager 类,那么 ICommand 呢?

现在对于 ICommand,它是 CommandBuilder

public class CommandBuilder : ICommand
    {
        private IConnection connection = null;
        private SqlConnection sqlConnection = null;
        public CommandBuilder()
        {
            connection = new ConnectionManager();
            sqlConnection = connection.Connection;
        }
        public string CommandText
        { get; set; }
        public string SpName
        { get; set; }
        public List<SqlParameter> SqlParams { get; set; }
        /// <summary>
        /// For Insert Update and Delete Queries
        /// </summary>
        /// <returns></returns>
        public bool Execute()
        {
            bool IsExecuted = false;
            using (sqlConnection)
            {
                try
                {
                    sqlConnection.Open();
                    using (var sqlCommand = new SqlCommand(CommandText, sqlConnection))
                    {
                        sqlCommand.CommandType = !string.IsNullOrWhiteSpace(CommandText) ? 
                                        CommandType.Text : CommandType.StoredProcedure;
                        sqlCommand.CommandText = !string.IsNullOrEmpty(CommandText) ?
                                        CommandText : SpName;
                        if (SqlParams != null)
                        {
                            SqlParams.ForEach(p => sqlCommand.Parameters.Add(p));
                        }
                        IsExecuted = sqlCommand.ExecuteNonQuery() > 0;
                    }
                }
                catch (Exception)
                {
                    //Handle Exception Here
                }

            }
            return IsExecuted;
        }

        /// <summary>
        /// /// For Select Queries
        /// </summary>
        /// <returns></returns>
        public DataSet SelectData()
        {
            var ds = new DataSet();
            using (sqlConnection)
            {
                try
                {
                    sqlConnection.Open();
                    using (var sqlCommand = new SqlCommand(CommandText, sqlConnection))
                    {
                        sqlCommand.CommandType = !string.IsNullOrWhiteSpace(CommandText) ? 
                            CommandType.Text : CommandType.StoredProcedure;
                        sqlCommand.CommandText = !string.IsNullOrEmpty(CommandText) ? 
                            CommandText : SpName;
                        SqlParams.ForEach(p => sqlCommand.Parameters.Add(p));
                        var adapter = new SqlDataAdapter(sqlCommand);
                        adapter.Fill(ds);
                    }
                }
                catch (Exception)
                {
                    //Handle Exception Here
                }

            }
            return ds;
        }
        
    }

这里构造函数从 ConnectionManager 类中为您提供连接。

   public CommandBuilder()
        {
            connection =  new ConnectionManager();
            sqlConnection = connection.Connection;
        } 

现在的属性是:

如果您将执行内联 SQL,则将 SQL 放入 CommandText 属性。

 public string CommandText // For Inline Sql
        { get; set; }    

如果您将执行存储过程,则将 Stored Procedure 名称放在 SpName 属性中。

        public string SpName // For Stored procedure
        { get; set; }   

如果您想传递 SqlParameter,则使用此 SqlParams

        public List<SqlParameter> SqlParams { get; set; }   

Execute 方法用于 Insert Update Delete 语句。

public bool Execute()
         

 SelectData 方法用于 Select 语句。

public DataSet SelectData()

现在是最后一个。 我必须对我的实体类施加一些特定的规则,以操作 CRUDExecuteSelectData 方法)。 这是在同一保护伞下的安排。 以下是我的类的保护伞或规则。

    interface ICrud<T> 
    {
        bool Insert(T obj);
        bool Update(T obj);
        bool Delete(T obj);
        DataSet Select(T obj);
    } 

 

关注点

现在如果我将该接口实现到我的 Employee 类会发生什么? 让我们看看

public class Employee:ICrud<ICommand>
    {
        public bool Insert(ICommand obj)
        {
            return obj.Execute();
        }
 
        public bool Update(ICommand obj)
        {
            return obj.Execute();
        }
 
        public bool Delete(ICommand obj)
        {
            return obj.Execute();
        }
 
        public DataSet Select(ICommand obj)
        {
          return  obj.SelectData();
        }
    }

哇,我的类不需要知道 SqlCommand, SqlConnection, SqlAdapter。 太棒了。 我将填充 ICommand 类型并传递,它将完成其余的工作。

我们如何从我的页面(客户端)调用这些方法? 非常简单。

          
            // FOR INLINE SQL
            var objEmployee = new Employee();
            var cmd = new CommandBuilder();
            cmd.CommandText = "SELECT ID,Name,Address FROM Employee";
            var dset = objEmployee.Select(cmd);

            // FOR STORED PROCEDURE
            var cmd = new CommandBuilder();
            cmd.SpName = "sp_InsertEmployee";
            cmd.SqlParams = new List<SqlParameter>()
            {
                new SqlParameter("@ID",123),
                new SqlParameter("@Name","Mark"),
                new SqlParameter("@Address","123 Park Street"),
            };
            var isInserted = objEmployee.Insert(cmd); 
客户端代码不需要知道 SqlConnection SqlCommand
© . All rights reserved.