使用Way.EntityDB進行Entity Framework Core數據庫建模


Way.EntityDB是一個基於EF Core的數據層框架,它取消了EF Core的Migration機制,因為Migration並不是通用的,比如說sql server生成的migration,如果換成sqlite,運行時會報錯的,也就是數據庫不能更換。

Way.EntityDB內置建模工具,通過圖形化建表,生成Model對象代碼,並且它會把表結構的修改過程,全部記錄下來,涵蓋在Model代碼里面,所以,在新的代碼運行時,數據庫也會自動更新到最新結構。

 舉個例子,當你把一個字段的名字從column1,更改為column2,EF Core生成的migration,就是把column1刪除,並添加一個column2,這樣,column1的現有數據就會丟失。而EntityDB則不一樣,它只會把column1改名為column2,

因為它記錄的是表結構修改的過程,而不是匹對Model類的前后變化。

 

Way.EntityDB源碼位置:

https://github.com/simpleway2016/EntityDB

啟動服務器端

Way.EntityDB是允許多人同時使用,所以,分為服務器和客戶端。

下載源碼,編譯后,在Debug/netcoreapp2.0文件夾里面,創建一個批處理文件run6062.bat,內容如下:

dotnet Way.EJServer.dll 6062

6062是本機任意一個沒有使用的端口號,表示以6062為端口,創建一個服務器工作空間

運行run6062.bat,啟動服務器端

 

運行客戶端

編譯並運行EJClient.exe

server url:https://localhost:6062

user name:sa

password:1

登錄進去,由於沒有工程項目,所以界面空白,點擊【project】菜單,創建一個項目

右鍵點擊【Database】,新建一個數據庫

再新建一個數據模塊UserInfo

雙擊UserInfo,在數據模塊里面,空白處點擊右鍵,新建數據表

 

 

 

這樣,一張數據表就創建完成

編程使用數據表

新建一個.net core 控制台項目

給這個項目安裝nuget包:Way.EntityDB

然后,回到EJClient,在TestDB處點擊右鍵,點擊【生成數據庫模型代碼】

保存到剛才創建的項目里面

 

 這樣,Model類就准備好了,開始寫代碼

using System;
using System.Linq;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            var db = new MyDB.DB.TestDB("data source='F:\\mytestdb.dat'", Way.EntityDB.DatabaseType.Sqlite);

            //插入數據
            var user = new MyDB.UserInfo() {
                UserName = "Jack",
                Password = "123"
            };

            //插入到數據庫
            db.Update(user);


            //從數據庫查詢數據
            var userlist = (from m in db.UserInfo select m).ToArray();

            //修改數據
            var jack = db.UserInfo.FirstOrDefault(m => m.UserName == "Jack");
            jack.Password = "567";
            db.Update(jack);

            //刪除數據
            db.Delete(jack);

//批量刪除
db.Delete(db.UserInfo.Where( m => m.id > 0 ));
} } }

 

從代碼可以看到,雖然也是EF Core,但由於禁用了ef的數據緩存機制,所以不能使用SaveChanges去同步數據庫,可以使用DBContext.Insert  DBContext.Update  DBContext.Delete等方法同步數據庫

DBContext.Update方法,會先判斷對象的主鍵,如果主鍵是Null,那么會調用Insert方法,往數據庫新增一條數據,如果主鍵不為Null,那么就是Update數據庫里面的數據

禁用緩存機制,可以避免程序員在編程的時候混亂(有時候想把數據取出來,看看現在的數據狀態,但誰知道取的是緩存里面的對象)

禁用緩存機制,對於大數據量的查詢,也可以節約內存,提供效率,因為不再使用的對象,不會保存在內存里面

所以整體性能,應該和使用ADO.Net差不多

編寫觸發器 

 Way.EntityDB支持類似觸發器的功能。添加一個ActionCapture類

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using Way.EntityDB;
using System.Linq;

namespace ConsoleApp1
{
    class UserInfoTrigger : Way.EntityDB.ActionCapture<MyDB.UserInfo>
    {
        public override void AfterInsert(object database, DatabaseModifyEventArg e)
        {
            MyDB.UserInfo user = (MyDB.UserInfo)e.DataItem;
            Debug.WriteLine($"inserted {user.UserName}");
            base.AfterInsert(database, e);
        }

        public override void BeforeDelete(object database, DatabaseModifyEventArg e)
        {
            var db = database as MyDB.DB.TestDB;
            //由於刪除的對象,可能只有主鍵有值,所以,需要獲取刪除對象的具體信息,需要到數據庫把該對象取出來
            var pkid = ((MyDB.UserInfo)e.DataItem).id;
            var deletingUser = db.UserInfo.FirstOrDefault( m=>m.id == pkid);

            Debug.WriteLine($"准備刪除 {deletingUser.UserName}");

            base.BeforeDelete(database, e);
        }

    }
}
class UserInfoTrigger : Way.EntityDB.ActionCapture<MyDB.UserInfo>  表示這個類捕獲的是UserInfo表的事件
這時候,這個類還不能起作用,必須在程序啟動時,把它實例化,注冊到DBContext里面
        static Program()
        {
            Way.EntityDB.DBContext.RegisterActionCapture(new UserInfoTrigger());
        }

在ActionCapture類里面,只要override各個方法,就可以實現各種事件的捕獲。

級聯刪除

 EJClient可以設置表之間的級聯刪除關系,並且,被級聯刪除的數據,同樣可以被你編寫的觸發器捕捉到。

現在,我們新建一張數據表FamilyInfo

雙擊UserInfo,打開屬性框,切換到【級聯刪除】項,添加一個級聯刪除關系

導航屬性(一對一)

雖然UserInfo和FamilyInfo,在數據庫中並沒有建立關系,但是,從系統設計上來說,他們是有關系的,所以,在UserInfo里面,如果可以直接訪問FamilyInfo,會比較方便,所以,

可以給他們添加導航屬性,首先,我們假設他們是一對一的關系。

打開UserInfo屬性窗口,切換到【導航屬性】,並添加一個名稱為Family的屬性

然后,打開FamilyInfo屬性窗口,添加一個User屬性

這里要注意,UserInfo里面的Family屬性,不需要選擇ForeignKey,而FamilyInfo的User屬性,必須選擇ForeignKey

接着用EJClient生成Model代碼

然后,代碼,我們可以這樣寫了

using System;
using System.Diagnostics;
using System.Linq;
using Microsoft.EntityFrameworkCore;

namespace ConsoleApp1
{
    class Program
    {
        static Program()
        {
            Way.EntityDB.DBContext.RegisterActionCapture(new UserInfoTrigger());
        }

        static void Main(string[] args)
        {
            var db = new MyDB.DB.TestDB("data source='F:\\mytestdb.dat'", Way.EntityDB.DatabaseType.Sqlite);

            //插入數據
            var user = new MyDB.UserInfo() {
                UserName = "Jack",
                Password = "123"
            };

            //插入到數據庫
            db.Update(user);

            //插入家庭信息
            var family = new MyDB.FamilyInfo() {
                UserId = user.id,
                MotherName = "李晴",
                FatherName = "劉星"
            };
            db.Update(family);

            //從數據庫查詢(m => m.Family 表示包含家庭信息)
            var jack = db.UserInfo.Include(m => m.Family).FirstOrDefault(m => m.UserName == "Jack");
            var montherName = jack.Family.MotherName;

            Debug.WriteLine($"mother is {montherName}");

            //刪除數據
            db.Delete(jack);
        }
    }
}
var montherName = jack.Family.MotherName;直接可以取到母親姓名,不需要到數據庫再取一遍

 導航屬性(一對多)

 如果UserInfo和FamilyInfo是一對多的關系,那么,打開userinfo對話框,把導航屬性改為這樣:

這時候,就必須選擇ForeignKey了

用工具再次生成Model代碼

這次的代碼,就是這樣寫了:

using System;
using System.Diagnostics;
using System.Linq;
using Microsoft.EntityFrameworkCore;

namespace ConsoleApp1
{
    class Program
    {
        static Program()
        {
            Way.EntityDB.DBContext.RegisterActionCapture(new UserInfoTrigger());
        }

        static void Main(string[] args)
        {
            var db = new MyDB.DB.TestDB("data source='F:\\mytestdb.dat'", Way.EntityDB.DatabaseType.Sqlite);

            //插入數據
            var user = new MyDB.UserInfo() {
                UserName = "Jack",
                Password = "123"
            };

            //插入到數據庫
            db.Update(user);

            //插入家庭信息
            var family1 = new MyDB.FamilyInfo() {
                UserId = user.id,
                MotherName = "李晴",
                FatherName = "劉星"
            };
            db.Update(family1);

            var family2 = new MyDB.FamilyInfo()
            {
                UserId = user.id,
                MotherName = "第二媽媽",
                FatherName = "第二爸爸"
            };
            db.Update(family2);

            //從數據庫查詢(m => m.Families 表示包含家庭信息)
            var jack = db.UserInfo.Include(m => m.Families).FirstOrDefault(m => m.UserName == "Jack");

            foreach (var family in jack.Families)
            {
                Debug.WriteLine($"mother is {family.MotherName}");
            }

            //刪除數據
            db.Delete(jack);
        }
    }
}

 變更數據庫類型

如果在開發過程中,你要變更數據庫類型,只需要更改連接字符串和類型即可

 var db = new MyDB.DB.TestDB("server=192.168.136.137;uid=sa;pwd=Sql12345678;Database=TestDB", Way.EntityDB.DatabaseType.SqlServer);

這樣,就轉而使用SqlServer數據庫


免責聲明!

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



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