EF實體框架之CodeFirst三


前兩篇博客學習了數據庫映射和表映射,今天學習下數據庫初始化、種子數據、EF執行sql以及執行存儲過程這幾個知識。

一、數據庫初始化策略

數據庫初始化有4種策略

策略一:數據庫不存在時重新創建數據庫

Database.SetInitializer<EFCodeFirstDbContext>(new CreateDatabaseIfNotExists<EFCodeFirstDbContext>());

策略二:每次啟動應用程序時創建數據庫

Database.SetInitializer<EFCodeFirstDbContext>(new DropCreateDatabaseAlways<EFCodeFirstDbContext>());

策略三:模型更改時重新創建數據庫

Database.SetInitializer<EFCodeFirstDbContext>(new DropCreateDatabaseIfModelChanges<EFCodeFirstDbContext>());

策略四:從不創建數據庫

Database.SetInitializer<EFCodeFirstDbContext>(null);

其中,在使用每次啟動應用程序時創建數據庫DropCreateDatabaseAlways時,總是報錯:無法刪除數據庫XXX,因為該數據庫當前正在使用,這個錯誤找了半天,在一篇帖子上寫讓選中數據庫,右鍵刪除,只選關閉連接復選框,之后就可以了,我也試了下,是可以的。

二、種子數據

對於新建的數據庫,可能會有一些默認的數據來做測試或默認配置,這時可以使用種子類來初始化數據庫數據。加入使用的是DropCreateDatabaseAlways策略,那么初始化器類就要從該泛型類繼承,並傳入數據庫上下文作為類型參數。接下來,要種子化數據庫就要重寫DropCreateDatabaseAlways類的Seed方法,而Seed方法拿到了數據庫上下文,因此我們可以使用它來將數據插入數據庫:

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using EFCodeFirstModels;

namespace EFCodeFirstDataAccess
{
    public class SeedingDataInitializer: DropCreateDatabaseAlways<EFCodeFirstDbContext>
    {
        protected override void Seed(EFCodeFirstDbContext context)
        {
            Person person = new Person("0002","cuiyanwei",SexType.Female,26);
            Person person1 = new Person("0003", "cuiyanwei1", SexType.Female, 25);
            context.Persons.Add(person);
            context.Persons.Add(person1);
            base.Seed(context);
        }
    }
}

上面的代碼中並沒有SaveChanges(),然后將將數據庫初始化器類用於數據庫上下文類

        public EFCodeFirstDbContext() : base("MyStrConn")
        {
            Database.SetInitializer<EFCodeFirstDbContext>(new SeedingDataInitializer());
        }

此時初始化種子,就不能在OnModelCreating中執行數據庫初始化策略了。

Database.SetInitializer<EFCodeFirstDbContext>(new DropCreateDatabaseAlways<EFCodeFirstDbContext>());

三、執行SQL語句

有時候在code first中也會執行sql來做查詢,或者是查詢視圖。

            //using能及時釋放資源,例如數據庫連接異常,可以即使將上下文釋放
            using (var db=new EFCodeFirstDbContext())
            {
                List<Person> persons=  db.Database.SqlQuery<Person>("select * from Person where personId=@id",new SqlParameter("@id","0002")).ToList();
                foreach (var person in persons)
                {
                    Console.WriteLine("{0}  {1}  {2}  {3}",person.PersonId,person.Name,person.Age,person.Sex);
                }
            }
            Console.ReadLine();

然后在數據庫中建一個視圖TestView,不過查詢的還是Person,其實也可以查詢部分字段,那樣還要再創建Model,因為懶所以還是使用Person。此時我們就不能使用DropCreateDatabaseAlways策略模式了,這樣的話數據的視圖這些都會不存在。我們可以使用CreateDatabaseIfNotExists策略模式,初始化數據時只需把SeedingDataInitializer類繼承自CreateDatabaseIfNotExists就OK了。

            //using能及時釋放資源,例如數據庫連接異常,可以即使將上下文釋放
            using (var db=new EFCodeFirstDbContext())
            {
                List<Person> persons=  db.Database.SqlQuery<Person>("select * from TestView where personId=@id", new SqlParameter("@id","0002")).ToList();
                foreach (var person in persons)
                {
                    Console.WriteLine("{0}  {1}  {2}  {3}",person.PersonId,person.Name,person.Age,person.Sex);
                }
            }
            Console.ReadLine();

四、執行存儲過程

有時候使用sql能解決的問題使用ef就不那么簡單,比如查找樹的某個節點的所有父節點或所有子節點。如果使用存儲過程那就會很容易,不過存儲過程也有弊端,例如只能返回一個表,不能同時返回多個表,可能是有我沒找到吧。

CREATE PROCEDURE TestProcedure
    @personId nvarchar(100)
AS
BEGIN
    select * from Person where PersonId=@personId;
END
GO

上面創建一個有一個參數的存儲過程,來查詢person。

                List<Person> persons = db.Database.SqlQuery<Person>("TestProcedure @personId", new SqlParameter("@personId", "0003")).ToList();
                foreach (var person in persons)
                {
                    Console.WriteLine("{0}  {1}  {2}  {3}",person.PersonId,person.Name,person.Age,person.Sex);
                }

上面的都是查詢使用的都是SqlQuery,如果需要更新操作可以使用ExecuteSqlCommand方法。

               int count=  db.Database.ExecuteSqlCommand("update Person set Name=@name where PersonId=@personId",new[] { new SqlParameter("@name", "CYW"), new SqlParameter("@personId", "0003") });
               Console.WriteLine(count);

從上面截圖可以看到已經將personId=0003的Name改為CYW,之前都是cuiyanwei。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM