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
来源: https://www.cnblogs.com/cc1027cc/p/11098437.html