首頁 > 軟體

Entity Framework中執行sql語句

2022-03-01 13:01:16

一、為什麼要在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語句的文章就介紹到這了。希望對大家的學習有所幫助,也希望大家多多支援it145.com。


IT145.com E-mail:sddin#qq.com