asp.net core 實(shí)戰(zhàn)項(xiàng)目(一)——ef core的使用

本文為轉(zhuǎn)載牧挣,原文:asp.net core 實(shí)戰(zhàn)項(xiàng)目(一)——ef core的使用

數(shù)據(jù)庫設(shè)計(jì)

數(shù)據(jù)結(jié)構(gòu)圖如下:



此次實(shí)例比較簡單靡砌,暫時(shí)只設(shè)計(jì)到上述3張表

SMUser:用于存儲用戶信息廊鸥。
Role:用于存儲角色信息。
SMUser_Role:用建立用戶和角色關(guān)系的一直關(guān)聯(lián)表。

創(chuàng)建項(xiàng)目

開發(fā)工具:visual studio 2015
打開vs2015->新建項(xiàng)目->.NET Core->ASP.NET Core Application(.Net core)
如下圖:



給自己的項(xiàng)目取個(gè)名字,選個(gè)路徑诉稍,就完事了。
然后在自己創(chuàng)建的解決方案里再新增個(gè)類庫項(xiàng)目最疆,此類庫項(xiàng)目用于實(shí)現(xiàn)數(shù)據(jù)庫的交互杯巨,也是實(shí)現(xiàn)EF Core的地方,如下圖:



我創(chuàng)建的項(xiàng)目結(jié)構(gòu)如下圖所示:

之后便是引用的添加了:
App項(xiàng)目引用DAL

DAL項(xiàng)目使用Nuget添加以下引用:

Microsoft.EntityFrameworkCore
Microsoft.EntityFrameworkCore.SqlServer
Microsoft.EntityFrameworkCore.Tools

DAL實(shí)現(xiàn)

Entities

在DAL項(xiàng)目中新建Entities文件夾努酸,該文件夾用于建立與數(shù)據(jù)庫表一一對應(yīng)的實(shí)體類服爷。我們根據(jù)數(shù)據(jù)庫結(jié)構(gòu),創(chuàng)建一下3個(gè)實(shí)體類。
SMUser:

using System;
using System.Collections.Generic;
namespace SnmiOA.DAL.Entities
{
    public class SMUser
    {
        public Guid SMUserId { get; set; }
        public string SSOUserName { get; set; }
        public string SSOPassword { get; set; }
        public string TrueName { get; set; }
        public bool IsValid { get; set; }
        public string Mobile { get; set; }
        public string Email { get; set; }
        public string UserNo { get; set; }
        public string EmployeeNo { get; set; }
        public string QQ { get; set; }
        public virtual ICollection<SMUserRole> SMUserRoles { get; set; }
    }
}

Role:

using System;
using System.Collections.Generic;
namespace SnmiOA.DAL.Entities
{
    public class Role
    {
        public Guid RoleId { get; set; }
        public string RoleName { get; set; }
        public int OrderField { get; set; }
        public virtual ICollection<SMUserRole> SMUserRoles { get; set; }
    }
}

SMUserRole

using System;
namespace SnmiOA.DAL.Entities
{
    public class SMUserRole
    {
        public Guid SMUserId { get; set; }
        public Guid RoleId { get; set; }
        public virtual Role Role { get; set; }
        public virtual SMUser SMUser { get; set; }
    }
}

DbContext實(shí)現(xiàn)

在DAL項(xiàng)目下添加SnmiOAContext.cs文件仍源。其代碼如下:

public class SnmiOAContext : DbContext
    {
       public SnmiOAContext(DbContextOptions<SnmiOAContext> options) : base(options) { }

        public DbSet<SMUser> SMUsers { get; set; }
        public DbSet<Role> Roles { get; set; }
        public DbSet<SMUserRole> SMUserRoles { get; set; }
    }

然后我們需要添加一下3張表之間的映射關(guān)系心褐,通過表結(jié)構(gòu)可以看出來,實(shí)際上我們的SMUser和Role之間是多對多的關(guān)系笼踩,SMUser_Role是兩張表產(chǎn)生的一張中間表檬寂,在以前的EF中這兩張表可以直接映射多對多的關(guān)系。但是在EF Core中目前我還沒有發(fā)現(xiàn)這種映射關(guān)系的寫法戳表,可能是我閱讀的資料還不夠,也可能是真的沒有提供這種映射昼伴。后來我就找到個(gè)把他們都分別改成一對多的關(guān)系來寫匾旭,發(fā)現(xiàn)也是可以的。代碼如下:

protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<SMUserRole>()
                .ToTable("SMUser_Role")
                .HasKey(ur => new { ur.RoleId, ur.SMUserId });
            modelBuilder.Entity<SMUserRole>()
                .HasOne(ur => ur.SMUser)
                .WithMany(u => u.SMUserRoles)
                .HasForeignKey(ur => ur.SMUserId);
            modelBuilder.Entity<SMUserRole>()
                .HasOne(ur => ur.Role)
                .WithMany(r => r.SMUserRoles)
                .HasForeignKey(ur => ur.RoleId);
            modelBuilder.Entity<SMUser>()
                .ToTable("SMUser")
                .HasKey(u => u.SMUserId);
            modelBuilder.Entity<SMUser>()
                .HasMany(u => u.SMUserRoles)
                .WithOne(ur => ur.SMUser)
                .HasForeignKey(u => u.SMUserId);
            modelBuilder.Entity<Role>()
                .ToTable("Role")
                .HasKey(r => r.RoleId);
            modelBuilder.Entity<Role>()
                .HasMany(r => r.SMUserRoles)
                .WithOne(ur => ur.Role)
                .HasForeignKey(ur => ur.RoleId);
        }

如果大家有更好的方法圃郊,還請告知价涝,謝謝!
最后持舆,別忘記了DBContext的依賴注入色瘩。
我們在APP項(xiàng)目的StartUp文件的ConfigureServices方法中添加以下代碼:

services.AddDbContext<SnmiOAContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("SnmiOAConnection")));

整體看上去應(yīng)該是這樣:

public void ConfigureServices(IServiceCollection services)
        {
            // Add framework services.
 services.AddApplicationInsightsTelemetry(Configuration);
            services.AddDbContext<SnmiOAContext>(options =>
 options.UseSqlServer(Configuration.GetConnectionString("SnmiOAConnection")));
            services.AddMvc();
        }

Repository實(shí)現(xiàn)

當(dāng)我們使用不同的數(shù)據(jù)模型和領(lǐng)域模型時(shí),倉儲模式特別有用逸寓。倉儲可以充當(dāng)數(shù)據(jù)模型和領(lǐng)域模型之間的中介居兆。在內(nèi)部,倉儲以數(shù)據(jù)模型的形式和數(shù)據(jù)庫交互竹伸,然后給數(shù)據(jù)訪問層之上的應(yīng)用層返回領(lǐng)域模型泥栖。

在我們這個(gè)例子中,因?yàn)槭褂昧藬?shù)據(jù)模型作為領(lǐng)域模型勋篓,因此吧享,也會返回相同的模型。如果想要使用不同的數(shù)據(jù)模型和領(lǐng)域模型譬嚣,那么需要將數(shù)據(jù)模型的值映射到領(lǐng)域模型或使用任何映射庫執(zhí)行映射钢颂。

現(xiàn)在定義倉儲接口IRepository如下:

using System;
using System.Linq;
using System.Linq.Expressions;
namespace SnmiOA.DAL.Repository
{
    public interface IRepository<T> where T :class
    {
        IQueryable<T> GetAllList(Expression<Func<T, bool>> predicate = null);
        T Get(Expression<Func<T, bool>> predicate);
        void Insert(T entity);
        void Delete(T entity);
        void Update(T entity);
        long Count();
    }
}

上面的幾個(gè)方法都是常見的CRUD操作,就不解釋了.
然后再實(shí)現(xiàn)一個(gè)倉儲類的泛型基類拜银,用來實(shí)現(xiàn)IRepository接口殊鞭,代碼如下:

using Microsoft.EntityFrameworkCore;
using System;
using System.Linq;
using System.Linq.Expressions;
namespace SnmiOA.DAL.Repository
{
    public class RepositoryBase<T> : IRepository<T> where T : class
    {
        private readonly SnmiOAContext _context = null;
        private readonly DbSet<T> _dbSet;
        public RepositoryBase(SnmiOAContext context)
        {
            _context = context;
            _dbSet = _context.Set<T>();
        }
        public long Count()
        {
            return _dbSet.LongCount();
        }
        public void Delete(T entity)
        {
            _dbSet.Remove(entity);
        }
        public T Get(Expression<Func<T, bool>> predicate)
        {
            return _dbSet.FirstOrDefault(predicate);
        }
        public IQueryable<T> GetAllList(Expression<Func<T, bool>> predicate = null)
        {
            if (predicate == null)
            {
                return _dbSet;
            }
            return _dbSet.Where(predicate);
        }
        public void Insert(T entity)
        {
            _dbSet.Add(entity);
        }
        public void Update(T entity)
        {
            _dbSet.Attach(entity);
            _context.Entry(entity).State = EntityState.Modified;
        }
    }
}

這樣每個(gè)實(shí)體類的倉儲類實(shí)現(xiàn)起來,就非常簡單了盐股,如下:

using SnmiOA.DAL.Entities;
namespace SnmiOA.DAL.Repository
{
    public class RoleRepository : RepositoryBase<Role>
    {
        public RoleRepository(SnmiOAContext context) : base(context)
        {
        }
    }
}

再安裝上述代碼分別為SMUser和SMUserRole建立倉儲類钱豁,如果需要更復(fù)雜的數(shù)據(jù)庫查詢操作,可以上上述倉儲類中補(bǔ)充實(shí)現(xiàn)疯汁。

UnitOfWork實(shí)現(xiàn)

我們已經(jīng)知道牲尺,DbContext默認(rèn)支持事務(wù),當(dāng)實(shí)例化一個(gè)新的DbContext對象時(shí),就會創(chuàng)建一個(gè)新的事務(wù)谤碳,當(dāng)調(diào)用SaveChanges方法時(shí)溃卡,事務(wù)會提交。問題是蜒简,如果我們使用相同的DbContext對象把多個(gè)代碼模塊的操作放到一個(gè)單獨(dú)的事務(wù)中瘸羡,該怎么辦呢?答案就是工作單元(Unit of Work)搓茬。

工作單元本質(zhì)是一個(gè)類犹赖,它可以在一個(gè)事務(wù)中跟蹤所有的操作,然后將所有的操作作為原子單元執(zhí)行卷仑【澹看一下倉儲類,可以看到DbContext對象是從外面?zhèn)鹘o它們的锡凝。此外粘昨,所有的倉儲類都沒有調(diào)用SaveChanges方法,原因在于窜锯,我們在創(chuàng)建工作單元時(shí)會將DbContext對象傳給每個(gè)倉儲张肾。當(dāng)想保存修改時(shí),就可以在工作單元上調(diào)用SaveChanges方法锚扎,也就在DbContext類上調(diào)用了SaveChanges方法吞瞪。這樣就會使得涉及多個(gè)倉儲的所有操作成為單個(gè)事務(wù)的一部分。

這里定義我們的工作單元類如下:

using SnmiOA.DAL.Repository;
using System;
namespace SnmiOA.DAL
{
    public class UnitOfWork : IDisposable
    {
        private readonly SnmiOAContext _context = null;
        private SMUserRepository _userRepository = null;
        private SMUserRoleRepository _userRoleRepository = null;
        private RoleRepository _roleRepository = null;

        public UnitOfWork(SnmiOAContext context)
        {
            _context = context;
        }
        public SMUserRepository SMUserRepository
        {
            get { return _userRepository ?? (_userRepository = new SMUserRepository(_context)); }
        }
        public SMUserRoleRepository SMUserRoleRepository
        {
            get { return _userRoleRepository ?? (_userRoleRepository = new SMUserRoleRepository(_context)); }
        }
        public RoleRepository RoleRepository
        {
            get
            {
                return _roleRepository ?? (_roleRepository = new RoleRepository(_context));
            }
        }
        public void SaveChanges()
        {
            _context.SaveChanges();
        }
        public void Dispose()
        {
            throw new NotImplementedException();
        }
    }
}

本文為原創(chuàng)工秩,轉(zhuǎn)載請注明出處

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末尸饺,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子助币,更是在濱河造成了極大的恐慌浪听,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件眉菱,死亡現(xiàn)場離奇詭異迹栓,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)俭缓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進(jìn)店門克伊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人华坦,你說我怎么就攤上這事愿吹。” “怎么了惜姐?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵犁跪,是天一觀的道長椿息。 經(jīng)常有香客問我,道長坷衍,這世上最難降的妖魔是什么寝优? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮枫耳,結(jié)果婚禮上乏矾,老公的妹妹穿的比我還像新娘。我一直安慰自己迁杨,他們只是感情好钻心,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著铅协,像睡著了一般扔役。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上警医,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天,我揣著相機(jī)與錄音坯钦,去河邊找鬼预皇。 笑死,一個(gè)胖子當(dāng)著我的面吹牛婉刀,可吹牛的內(nèi)容都是我干的吟温。 我是一名探鬼主播,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼突颊,長吁一口氣:“原來是場噩夢啊……” “哼鲁豪!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起律秃,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤爬橡,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后棒动,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體糙申,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年船惨,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了柜裸。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,711評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡粱锐,死狀恐怖疙挺,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情怜浅,我是刑警寧澤铐然,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響锦爵,放射性物質(zhì)發(fā)生泄漏舱殿。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一险掀、第九天 我趴在偏房一處隱蔽的房頂上張望沪袭。 院中可真熱鬧,春花似錦樟氢、人聲如沸冈绊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽死宣。三九已至,卻和暖如春碴开,著一層夾襖步出監(jiān)牢的瞬間毅该,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工潦牛, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留眶掌,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓巴碗,卻偏偏與公主長得像朴爬,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子橡淆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評論 2 353

推薦閱讀更多精彩內(nèi)容