你的位置:首页 > ASP.net教程

[ASP.net教程]EntityFramework与Ado.net的对比——EF优势何在?


更准确的说法是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;      }    }  }

SqlHelper

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));    }  }

GroupInfoDal
    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);      }    }

InsertTest

使用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;    }

Update指定属性

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,代码可读性更高。

...

如果有错误,请大家指出。如果有遗漏,请帮助完善。