数据库设计

数据结构图如下:

 

此次实例比较简单,暂时只设计到上述3张表

SMUser:用于存储用户信息。
Role:用于存储角色信息。
SMUser_Role:用建立用户和角色关系的一直关联表。

创建项目

开发工具:visual studio 2015
打开vs2015->新建项目->.NET Core->ASP.NET Core Application(.Net core)
如下图:

 
 

给自己的项目取个名字,选个路径,就完事了。
然后在自己创建的解决方案里再新增个类库项目,此类库项目用于实现数据库的交互,也是实现EF Core的地方,如下图:

 
 

我创建的项目结构如下图所示:

 
 

之后便是引用的添加了:
App项目引用DAL

DAL项目使用Nuget添加以下引用:

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

DAL实现

Entities

在DAL项目中新建Entities文件夹,该文件夹用于建立与数据库表一一对应的实体类。我们根据数据库结构,创建一下3个实体类。
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实现

在DAL项目下添加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张表之间的映射关系,通过表结构可以看出来,实际上我们的SMUser和Role之间是多对多的关系,SMUser_Role是两张表产生的一张中间表,在以前的EF中这两张表可以直接映射多对多的关系。但是在EF Core中目前我还没有发现这种映射关系的写法,可能是我阅读的资料还不够,也可能是真的没有提供这种映射。后来我就找到个把他们都分别改成一对多的关系来写,发现也是可以的。代码如下:

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项目的StartUp文件的ConfigureServices方法中添加以下代码:

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

整体看上去应该是这样:

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

Repository实现

当我们使用不同的数据模型和领域模型时,仓储模式特别有用。仓储可以充当数据模型和领域模型之间的中介。在内部,仓储以数据模型的形式和数据库交互,然后给数据访问层之上的应用层返回领域模型。

在我们这个例子中,因为使用了数据模型作为领域模型,因此,也会返回相同的模型。如果想要使用不同的数据模型和领域模型,那么需要将数据模型的值映射到领域模型或使用任何映射库执行映射。

现在定义仓储接口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();
}
}

上面的几个方法都是常见的CRUD操作,就不解释了.

然后再实现一个仓储类的泛型基类,用来实现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;
}
}
}

这样每个实体类的仓储类实现起来,就非常简单了,如下:

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

再安装上述代码分别为SMUser和SMUserRole建立仓储类,如果需要更复杂的数据库查询操作,可以上上述仓储类中补充实现。

UnitOfWork实现

我们已经知道,DbContext默认支持事务,当实例化一个新的DbContext对象时,就会创建一个新的事务,当调用SaveChanges方法时,事务会提交。问题是,如果我们使用相同的DbContext对象把多个代码模块的操作放到一个单独的事务中,该怎么办呢?答案就是工作单元(Unit of Work)。

工作单元本质是一个类,它可以在一个事务中跟踪所有的操作,然后将所有的操作作为原子单元执行。看一下仓储类,可以看到DbContext对象是从外面传给它们的。此外,所有的仓储类都没有调用SaveChanges方法,原因在于,我们在创建工作单元时会将DbContext对象传给每个仓储。当想保存修改时,就可以在工作单元上调用SaveChanges方法,也就在DbContext类上调用了SaveChanges方法。这样就会使得涉及多个仓储的所有操作成为单个事务的一部分。

这里定义我们的工作单元类如下:

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();
}
}
}

作者:ChainZhang
链接:https://www.jianshu.com/p/292d0eeb8afb
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

asp.net core 实战项目(一)——ef core的使用的更多相关文章

  1. .NET Core实战项目之CMS 第二章 入门篇-快速入门ASP.NET Core看这篇就够了

    作者:依乐祝 原文链接:https://www.cnblogs.com/yilezhu/p/9985451.html 本来这篇只是想简单介绍下ASP.NET Core MVC项目的(毕竟要照顾到很多新 ...

  2. ASP.NET Core 开发-Entity Framework (EF) Core 1.0 Database First

    ASP.NET Core 开发-Entity Framework Core 1.0 Database First,ASP.NET Core 1.0 EF Core操作数据库. Entity Frame ...

  3. ASP.NET Core 开发 - Entity Framework (EF) Core

    EF Core 1.0 Database First http://www.cnblogs.com/linezero/p/EFCoreDBFirst.html ASP.NET Core 开发 - En ...

  4. .NET Core实战项目之CMS 第一章 入门篇-开篇及总体规划

    作者:依乐祝 原文地址:https://www.cnblogs.com/yilezhu/p/9977862.html 写在前面 千呼万唤始出来,首先,请允许我长吸一口气!真没想到一份来自28岁老程序员 ...

  5. .NET Core实战项目之CMS 第三章 入门篇-源码解析配置文件及依赖注入

    作者:依乐祝 原文链接:https://www.cnblogs.com/yilezhu/p/9998021.html 写在前面 上篇文章我给大家讲解了ASP.NET Core的概念及为什么使用它,接着 ...

  6. .NET Core实战项目之CMS 第四章 入门篇-Git的快速入门及实战演练

    写在前面 上篇文章我带着大家通过分析了一遍ASP.NET Core的源码了解了它的启动过程,然后又带着大家熟悉了一遍配置文件的加载方式,最后引出了依赖注入以及控制反转的概念!如果大家把前面几张都理解了 ...

  7. .NET Core实战项目之CMS 第五章 入门篇-Dapper的快速入门看这篇就够了

    写在前面 上篇文章我们讲了如在在实际项目开发中使用Git来进行代码的版本控制,当然介绍的都是比较常用的功能.今天我再带着大家一起熟悉下一个ORM框架Dapper,实例代码的演示编写完成后我会通过Git ...

  8. .NET Core实战项目之CMS 第六章 入门篇-Vue的快速入门及其使用

    写在前面 上面文章我给大家介绍了Dapper这个ORM框架的简单使用,大伙会用了嘛!本来今天这篇文章是要讲Vue的快速入门的,原因是想在后面的文章中使用Vue进行这个CMS系统的后台管理界面的实现.但 ...

  9. .NET Core实战项目之CMS 第七章 设计篇-用户权限极简设计全过程

    写在前面 这篇我们对用户权限进行极简设计并保留其扩展性.首先很感谢大家的阅读,前面六章我带着大家快速入门了ASP.NET Core.ASP.NET Core的启动过程源码解析及配置文件的加载过程源码解 ...

  10. .NET Core实战项目之CMS 第九章 设计篇-白话架构设计

    前面两篇文章给大家介绍了我们实战的CMS系统的数据库设计,源码也已经上传到服务器上了.今天我们就好聊聊架构设计,在开始之前先给大家分享一下这几天我一直在听的<从零开始学架构>里面关于架构设 ...

随机推荐

  1. 用 jupyter notebook 打开 oui.txt 文件出现的问题及解决方案

    问题背景:下载了2018 IEEE 最新的 oui.txt 文件.里面包含了 设备 MAC 地址的前六位对应的厂商.要做的工作是,将海量设备的 MAC 地址与 oui.txt 文件的信息比对,统计出 ...

  2. Java JDK下载、安装和验证

    1.JDK下载地址: http://www.oracle.com/technetwork/java/javase/downloads/index.html,点开链接看到如下图所示的界面: 2.点击上图 ...

  3. Python Django Web开发的5个优秀好习惯

    https://blog.csdn.net/weixin_42134789/article/details/82381854

  4. maven install报错 Failed to execute goal on project my-manager-mapper: Could not resolve dependencies for project com.my:my-manager-mapper:jar:0.0.1-SNAPSHOT:

    报错信息为: [ERROR] Failed to execute goal on project my-manager-mapper: Could not resolve dependencies f ...

  5. 函数调用模式,this指向

    ## 函数的四种调用模式 1.函数模式    this--->window function test(){ console.log(this); } test(): 2.方法模式    thi ...

  6. Educational Codeforces Round 41 (Rated for Div. 2)F. k-substrings

    题意比较麻烦略 题解:枚举前缀的中点,二分最远能扩展的地方,lcp来check,然后线段树维护每个点最远被覆盖的地方,然后查询线段树即可 //#pragma GCC optimize(2) //#pr ...

  7. MongoVUE的table view视图不显示列标题

    近来项目用到mongodb,遂装了个MongoVUE,当然是破解版的. 但是发现个小问题,就是table view视图下列标题文字标签不见了,Find的执行按钮也是空白一片: 开始以为破解的不彻底,重 ...

  8. 修改 input / textarea placeholder 属性的颜色和字体大小

    话不多说,直接上代码: input::-webkit-input-placeholder, textarea::-webkit-input-placeholder { color: #666; fon ...

  9. 小程序input组件获得焦点时placeholder内容有重影

    这个问题是小程序input组件的bug,目前的解决办法可以,在input标签上加一个其他标签,显示placeholder内容,获得焦点时消失,失去焦点时候再让其显示 <view class='i ...

  10. 给MS的意见

    2017-02-27 WPF的中文注释文档翻译得很烂.太多了,列举不过来. 这个是 System.Threading.Tasks.Task.Exception: 获取导致 System.Aggrega ...