Asp.Net Core 專案 EntityFramework Core 根據登入使用者名稱過濾資料
1、建立ASP.NET Core Web Applicatoin (MVC)專案,並且使用 Individual User Account
2、建立資料篩選介面 Models->IDataFilter.cs
public interface IDataFilter { string UserName { get; set; } }
3、建立實體 Models->Book.cs 並繼承 IDataFilter介面,並將實體加入到 Data->ApplicatoinDbContext.cs 上下文中.
public class Book : IDataFilter { public int Id { get; set; } [Display(Name = "書名")] public string Name { get; set; } public string UserName { get; set; } }
public class ApplicationDbContext : IdentityDbContext { public DbSet<Book> Books { get; set; } public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { } }
4、利用模板建立Book類的 CRUD介面。在 Controllers資料夾上 右鍵 選擇 Add(新增)->Controller(控制器)
5、自動生成Book的增刪改查之後,我們在這裡要做一個細微的修改,因為我們IDataFilter欄位 UserName是系統生成的,所以我們要修改兩個地方
將BooksController.cs 下的 Create Action(由於只做演示,沒有去修改Update頁面)裡面的 Bind UserName去掉。修改後結果如下
並將建立頁面 Views->Books->Create.cshtml 中的 UserName 部份備註
在母版頁新增Book菜單鏈接 Views->Shared->_Layout.cshtml
6、開啟Nuget管理控制檯 遷移資料庫,並F5執行,點選Book連結。檢查一下程式 有沒問題。
Add-Migration Init //建立遷移檔案 Update-Database //更新到資料庫
7、由於Book實體實現了IDataFilter,UserName我們會通過重寫ApplicationDbContext的SaveChanges的實現,進行自動填充使用者名稱.由於要獲取登入資訊,在ApplicationDbContext中我們需注入 IHttpContextAccessor
public class ApplicationDbContext : IdentityDbContext { private readonly IHttpContextAccessor _httpContextAccessor; public DbSet<Book> Books { get; set; } public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options, IHttpContextAccessor httpContextAccessor) : base(options) { _httpContextAccessor = httpContextAccessor; } public override int SaveChanges() { FillDataFilterInfo(); return base.SaveChanges(); } public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = default) { FillDataFilterInfo(); return base.SaveChangesAsync(cancellationToken); } protected void FillDataFilterInfo() => ChangeTracker .Entries() .Where(w => w.Entity is IDataFilter && w.State == EntityState.Added) .ToList() .ForEach(entry => ((IDataFilter)entry.Entity).UserName = CurrentUserName); private string CurrentUserName => _httpContextAccessor.HttpContext.User?.Identity?.Name; }
8、驗證結果,執行專案,首先註冊一個帳號。然後進行建立一本書。最終結果。
9、最後我們來實現資料過濾部份程式碼,開啟 ApplicatonDbContex.cs
新增私有方法DataFilters
private void DataFilters<T>(ModelBuilder builder) where T : class { builder.Entity<T>().HasQueryFilter(s => ((IDataFilter)s).UserName == CurrentUserName); }
新增一個靜態MethodInfo方法。這裡用到返射實現
private static readonly MethodInfo _dataFiltersMethodInfo = typeof(ApplicationDbContext).GetMethod(nameof(DataFilters), BindingFlags.Instance | BindingFlags.NonPublic);
在重寫OnModelCreating ,針對所有實現 IDataFilter的實體新增資料過濾
protected override void OnModelCreating(ModelBuilder builder) { builder.Model .GetEntityTypes() .Where(w => typeof(IDataFilter).IsAssignableFrom(w.ClrType)) .ToList().ForEach(entityType => { _dataFiltersMethodInfo .MakeGenericMethod(entityType.ClrType) .Invoke(this, new object[] { builder }); }); base.OnModelCreating(builder); }
10、執行程式,分別用不同的瀏覽器。註冊兩個帳號。然後建立幾本書。最終結果
完結!第一次寫,見諒。
原始碼地址:https://github.com/CC1027CC/DataFilter
&n