Entity Framework中執行sql語句

一、為什麼要在EF中執行SQL語句

使用EF操作數據庫,可以避免寫SQL語句,完成使用Linq實現,但為什麼還要在EF中執行SQL語句呢。如果要寫SQL語句,完全可以使用ADO.NET來操作數據庫。這樣說雖然沒錯,可是有些時候使用EF操作數據庫還是有一些不方便的地方,例如:如果要修改某一條記錄,按照EF的正常流程走,需要先把要修改的數據查詢出來,然後在去修改,這樣不僅麻煩而且性能也低,這時直接使用EF執行SQL語句性能會提高很多。
而使用EF執行SQL又比ADO.NET方便,特別是在執行查詢語句的時候,EF會把查詢到的數據自動保存到數據實體中,省去瞭使用DataReader的麻煩。同時查詢出來的數據還會進行跟蹤,如果你修改瞭查詢出的值,之後就可以很方便的使用.SaveChanges()直接更新到數據庫瞭。
在數據上下文DbContext中有一個Database的屬性,Database屬性中有兩組方法:ExecuteSqlCommand()和SqlQuery()。這兩個方法都可以用來執行SQL語句,但這兩個方法也有不同點:ExecuteSqlCommand()是不返回結果的,隻返回受影響的行數,所以ExecuteSqlCommand()更適合用來執行創建、插入、更新、刪除操作(即執行給定的DDL/DML命令)。SqlQuery()則會返回查詢到的結果,並將結果保存在數據實體中,所以SqlQuery()更適合執行查詢操作。

二、使用ExecuteSqlCommand()執行創建、插入、更新、刪除語句

ExecuteSqlCommand()的使用方法很簡單,直接傳入SQL語句就可以瞭,執行完成後會返回受影響的行數。
在下面的例子中,entity是一個繼承自DbContext的對象。

1、執行創建語句

// 執行創建語句
string strCreateSQL = @"CREATE table test( id int primary key not null,name varchar(16),password varchar(20))";
 // 註意:執行create語句受影響的行數是-1
int result = entity.Database.ExecuteSqlCommand(strCreateSQL);
if (result.Equals(-1))
{
    Console.WriteLine("創建成功!");
}

 2、執行Insert語句

// 執行Insert語句
string strInsertSQL = @"INSERT INTO test
                                        SELECT 1,'小明','1234' UNION
                                        SELECT 2,'小王','1234' UNION
                                        SELECT 3,'小紅','1234'  ";
int result = entity.Database.ExecuteSqlCommand(strInsertSQL);
if (result > 0)
{
       Console.WriteLine("插入成功");
}

3、執行Update語句

// 執行Update語句
string strUpdateSQL = @"UPDATE test SET password=@pwd1 WHERE id=@id1;
UPDATE test SET password=@pwd2 WHERE id=@id2;";
                SqlParameter[] para =  {
                   new  SqlParameter("@pwd1","ceshi12we"),
                   new  SqlParameter("@id1",1),
                   new  SqlParameter("@pwd2","ceshi127890"),
                   new  SqlParameter("@id2",2),
                };

int result = entity.Database.ExecuteSqlCommand(strUpdateSQL, para);
if (result > 0)
{
    Console.WriteLine("更新成功");
}

4、執行Delete語句

// 執行刪除語句
string strDelSQL = "delete from test";
int result = entity.Database.ExecuteSqlCommand(strDelSQL);
if (result > 0)
{
     Console.WriteLine("刪除成功");
}

5、執行Drop語句

string strDropSQL = "drop table test";
int result = entity.Database.ExecuteSqlCommand(strDropSQL);
if (result.Equals(-1))
{
    Console.WriteLine("刪除成功");
}

註意:執行DDL語句(create、alter、drop等)返回值是-1,DML(insert、update、delete)返回的是受影響的行數。

三、使用SqlQuery()查詢數據

SqlQuery()是用來執行查詢的。SqlQuery()使用前需要指定返回值的類型。返回值類型可以是定義的實體類型,或者基元類型。例如:查詢一個用戶的完整信息,返回類型就是用戶實體類型;如果是統計有多少個用戶,返回值就是int類型。
註意:返回值的個數和名稱必須和傳入的類型中屬性個數、名稱相同,不如會報錯。

在下面的例子中User是根據數據庫表生成的實體類型。

string strSQL = "SELECT * FROM Users WHERE ID>=10 ORDER BY ID DESC";
var info = entity.Database.SqlQuery<User>(strSQL);
foreach (var item in info)
{
       Console.WriteLine("ID:" + item.ID + " " + "登錄名:" + item.LoginName + " " + "密碼:" + item.Password);
}

運行結果:

前面說過返回值的個數和名稱必須和傳入的類型中屬性個數、名稱相同,不如會報錯。如果將SQL語句修改為隻查詢ID、登錄名、密碼會出現下面的錯誤:

如果隻想查詢ID、登錄名、密碼該怎麼辦呢?那就需要單獨定義一個類(隻包含ID、登錄名、密碼三個屬性)來保存數據.

新定義的類,隻包含ID、登錄名、密碼三個屬性:

public class newUser
{
        public int ID { get; set; }

        public string LoginName { get; set; }

        public string Password { get; set; }
}
// 方法四:SqlQuery
try
{
                string strSQL = "SELECT ID,LoginName,Password FROM Users WHERE ID>=10 ORDER BY ID DESC";
                var info = entity.Database.SqlQuery<newUser>(strSQL);
                foreach (var item in info)
                {
                    Console.WriteLine("ID:" + item.ID + " " + "登錄名:" + item.LoginName + " " + "密碼:" + item.Password);
                }
}
catch (Exception ex)
{
                Console.WriteLine(ex.Message);
}

運行結果:

返回值是基元類型:

查詢用戶數量,返回int類型

// 查詢用戶數量
string strSQL = "SELECT COUNT(*) FROM test";
var result = entity.Database.SqlQuery<int>(strSQL);
// 註意:必須使用循環才會真正的去數據庫執行SQL語句,否則不會再數據庫執行SQL語句(EF的延遲加載)
foreach(var item in result)
{
     Console.WriteLine("用戶數量:" + item.ToString());
}

運行結果:

四、使用DbSet<T>下的SqlQuery()

在每個數據實體集合DbSet<T>下也有一個SqlQuery(),功能與上面介紹的一樣,隻不過DbSet<T>下的SqlQuery()隻能返回DbSet<T>中包含的類型,DbSet<T>下的SqlQuery()在返回數據的同時還會讓數據庫上下文(DBContext)跟蹤返回數據的狀態,如果返回的數據發生瞭修改,就可以使用SaveChanges()將結果直接保存回數據庫。而Database.SqlQuery()查出的結果則不能跟蹤返回數據的狀態。

1、使用實體集合下面的SqlQuery()方法

string strSQL = "SELECT * FROM Users WHERE UserID='002068'";
User user = entity.Users.SqlQuery(strSQL).FirstOrDefault();
user.Password = "測試實體下面的SqlQuery方法";
// 調用SaveChanges()方法可以更新Password字段
entity.SaveChanges();

2、使用Database下的SqlQuery()方法

string strSQL = "SELECT * FROM Users WHERE UserID='002068'";
User user = entity.Database.SqlQuery<User>(strSQL).FirstOrDefault();
user.Password = "測試Database下面的SqlQuery方法";
// 調用SaveChanges()方法不可以更新Password字段
entity.SaveChanges();

如果希望使用Database下的SqlQuery()查詢出的數據在修改後也能保存到數據庫,可以使用下面的代碼:

string strSQL = "SELECT * FROM Users WHERE UserID='002068'";
User user = entity.Database.SqlQuery<User>(strSQL).FirstOrDefault();
user.Password = "測試Database下面的SqlQuery方法";
// 設置這條數據的狀態是:Modified,這樣可以通知數據上下文,這條記錄也被修改瞭
entity.Entry<User>(user).State = System.Data.Entity.EntityState.Modified;
// 調用SaveChanges()方法不可以更新Password字段
entity.SaveChanges();

到此這篇關於Entity Framework中執行sql語句的文章就介紹到這瞭。希望對大傢的學習有所幫助,也希望大傢多多支持WalkonNet。

推薦閱讀: