更准確的說法是EF對比SqlHelper ado.net

public class SqlHelper { public static readonly string connstr = "Server=.;Database=PhoneBook;Uid=sa;Pwd=********;"; //params 長度可變的參數. public static int ExecuteNonQuery(string sql, params SqlParameter[] parameters) { //a寫法 using (SqlConnection conn = new SqlConnection(connstr)) { conn.Open(); using (SqlCommand cmd = conn.CreateCommand()) { cmd.CommandText = sql; cmd.Parameters.AddRange(parameters); return cmd.ExecuteNonQuery(); } } //b寫法 //SqlConnection conn = new SqlConnection(connstr); //conn.Open(); //SqlCommand cmd = conn.CreateCommand(); //cmd.CommandText = sql; //cmd.Parameters.AddRange(parameters); //return cmd.ExecuteNonQuery(); } public static object ExecuteScalar(string sql, params SqlParameter[] parameters) { using (SqlConnection conn = new SqlConnection(connstr)) { conn.Open(); using (SqlCommand cmd = conn.CreateCommand()) { cmd.CommandText = sql; cmd.Parameters.AddRange(parameters); return cmd.ExecuteScalar(); } } } public static DataTable ExecuteDataTable(string sql, params SqlParameter[] parameters) { using (SqlConnection conn = new SqlConnection(connstr)) { conn.Open(); using (SqlCommand cmd = conn.CreateCommand()) { cmd.CommandText = sql; cmd.Parameters.AddRange(parameters); DataSet dataset = new DataSet(); SqlDataAdapter adapter = new SqlDataAdapter(cmd); adapter.Fill(dataset); return dataset.Tables[0]; } } } //可空數據的輸入: //SqlParameter中,如果是"",則數據庫中的數據為""或者0. //如何SqlParameter是Null,程序運行報錯"沒有提供參數." //如何表示數據庫中的Null?SqlParameter用DBNull.Value. //如果數據庫中的值是Null,AOD.net讀取為DBNull.Value.而該DBNull.Value不能轉換為string. //可空類型,int? bool? public static object FromDBValue(object value) { if (value == DBNull.Value) { return null; } else { return value; } } public static object ToDBValue(object value) { if (value == null) { return DBNull.Value; } else { return value; } } }
1. 新增操作.
使用EF:
var db = new PhoneBookEntities(); db.Database.Log = Console.Write;//打印sql語句 List<GroupInfo> list = new List<GroupInfo>(); list.Add(new GroupInfo() { GroupName = "li" }); list.Add(new GroupInfo() { GroupName = "ge" }); list.Add(new GroupInfo() { GroupName = "xiao" }); db.GroupInfo.AddRange(list); db.SaveChanges();
使用sql server profiler的監控結果:
使用SqlHelper

public class GroupInfoDAL { public GroupInfo ToGroupInfo(DataRow row) { GroupInfo model = new GroupInfo(); model.GroupId = (System.Int32)row["GroupId"]; model.GroupName = (System.String)row["GroupName"]; return model; } public GroupInfo GetById(int id) { DataTable table = SqlHelper.ExecuteDataTable("select * from GroupInfo where GroupId=@GroupId", new SqlParameter("@GroupId", id)); if (table.Rows.Count <= 0) { return null; } else if (table.Rows.Count > 1) { throw new Exception("Id 重復,屬於嚴重錯誤"); } else { DataRow row = table.Rows[0]; return ToGroupInfo(row); } } public void DeleteById(int id) { SqlHelper.ExecuteNonQuery("delete from GroupInfo where GroupId=@GroupId", new SqlParameter("@GroupId", id)); } public GroupInfo[] GetAll() { DataTable dt = SqlHelper.ExecuteDataTable("select * from GroupInfo"); GroupInfo[] models = new GroupInfo[dt.Rows.Count]; for (int i = 0; i < dt.Rows.Count; i++) { models[i] = ToGroupInfo(dt.Rows[i]); } return models; } public void Update(GroupInfo model) { SqlHelper.ExecuteNonQuery("update GroupInfo set GroupName=@GroupName where GroupId=@GroupId", new SqlParameter("@GroupId", model.GroupId), new SqlParameter("@GroupName", model.GroupName)); } public void Insert(GroupInfo model) { SqlHelper.ExecuteNonQuery("insert into GroupInfo(GroupName) values(@GroupName)", new SqlParameter("@GroupName", model.GroupName)); } }

static void InsertTest() { var giDal = new GroupInfoDAL(); List<GroupInfo> list=new List<GroupInfo>(); list.Add(new GroupInfo(){GroupName = "li"}); list.Add(new GroupInfo(){GroupName = "ge"}); list.Add(new GroupInfo(){GroupName = "xiao"}); foreach (var item in list) { giDal.Insert(item); } }
使用sql server profiler的監控結果:
測試結果:
EF:一次連接,執行3條sql.
SqlHelper里使用a寫法用using,會造成多次連接重置;
b寫法不用using,連接又無法釋放.
同樣,更新和刪除多條數據,也是一個道理.
甚至查詢上,也可以使用EntityFramework.Extended中Future,把多次查詢放到一個連接里.見 EntityFramework和EntityFramework.Extended使用說明——性能,語法和產生的sql
2. update
EF自動優化,只update set 有變化的字段.
EF也可以很方便地只更新實體的指定屬性,產生的sql語句里的set后的字段會更少.

public void Edit(TEntity model, string[] propertyNames) { //檢查model的合法性 if (model == null) { throw new Exception("model實體不能為Null"); } //屬性propertyNames至少有一個 if (propertyNames == null || propertyNames.Any() == false) { throw new Exception("propertyNames數組至少要有一個值"); } var entry = db.Entry(model); entry.State = EntityState.Unchanged; foreach (var item in propertyNames) { entry.Property(item).IsModified = true; } db.Configuration.ValidateOnSaveEnabled = false; }
3. 只查詢表的指定字段
SqlHelper把查到的數據表的每一行轉換為一個對象.那么sql語句:select * from ... 而這種sql寫法是不推薦的.
要解決這個問題,有點麻煩吧?(有好方法的可以留言.希望回答時考慮到DTO,domain model,復雜的業務肯定會用到.)
而使用EF里的select投影方法輕松搞定,只在sql語句里'select'需要的字段.
4.用linq, lamda表達式 有智能提示,寫錯了編譯不過.
寫sql語句字符串,調sqlhelper,sql語句寫錯一樣編譯通過.
5.安全上,省去了防止sql注入的麻煩.
6.使用EF,數據庫變更切換較方便
雖然使用的數據庫在項目開始就會確定,誰又能保證沒有奇葩的數據庫變更的需求呢?
如果你使用的是EF,你就呵呵一笑,這事兒小菜一碟.
7.開發效率上.使用EF要比使用Ado.net開發效率高.
目前我用的Database First,會直接產生實體類(代碼生成功能);
如果是Code First,也會創建對應的數據庫.還是很方便的.這只是一個小方面.
更主要的是使用EF會更方便地操作數據庫.
8.代碼的可讀性.
使用EF,代碼可讀性更高。
...
如果有錯誤,請大家指出。如果有遺漏,請幫助完善。