1.示例简介
公司会有很多网站,我们可以把这些网站地址都配置在数据库中,在公司的门户网站上显示出来,这样用户就只要登录门户网站就行,用户可以通过点击门户网站的图标来访问其他的网站,该案例最终效果图如下
2.创建一个ASP.NET Core WebApi项目
项目创建成功后,打开Properties\launchSettings.json文件,把端口号设置为5000
因为使用的是SqlServer数据库,这里需要添加EntityFrameworkCore包和EntityFrameworkCore.SqlServer包
Microsoft.EntityFrameworkCore
Microsoft.EntityFrameworkCore.SqlServer
项目结构如下图
3.使用EF和数据库建立连接
3.1 数据表
该示例用到三张表,在每个表中都插入了一些数据
Base_DataDictionary:数据字典表
Base_DataDictionaryDetail:数据字典详细表,这个表的ParentId就是上面表的Id
Base_Setting:用户配置表,存储用户在首页上显示的图标
3.2 Entities
在项目中新建Entities文件夹,该文件夹用来存放与数据表一一对应的实体类,根据数据结构,创建下面4个实体类
EntityBase:这个实体用来存放数据表都有的一些基础字段
public abstract class EntityBase
{
[Key]
public Guid Id { get; set; }
public bool IsDelete { get; set; }
public Guid? ParentId { get; set; }
public DateTime? CreateTime { get; set; }
public Guid? CreateUserId { get; set; }
public DateTime? ModifyTime { get; set; }
public Guid? ModifyUserId { get; set; }
}
DataDictionary
[Table("Base_DataDictionary")]
public class DataDictionary : EntityBase
{
public string Code { get; set; }
public string FullName { get; set; }
public string ShortName { get; set; }
public int? SortCode { get; set; }
public virtual ICollection<DataDictionaryDetail> Details { get; set; }
}
DataDictionaryDetail
[Table("Base_DataDictionaryDetail")]
public class DataDictionaryDetail : EntityBase
{
public string Code { get; set; }
public string FullName { get; set; }
public string ShortName { get; set; }
public int? SortCode { get; set; }
[Column("Ext1")]
public string ImagePath { get; set; }
[Column("Ext2")]
public string RedirectUrl { get; set; }
public virtual DataDictionary Dictionary { get; set; }
}
Setting
[Table("Base_Seeting")]
public class Setting
{
[Key]
public Guid Id { get; set; }
public Guid? DetailId { get; set; }
public Guid? UserId { get; set; }
public int? SortCode { get; set; }
[NotMapped]
public bool IsDelete { get; set; }
}
3.3 DbContext实现
在项目中新建Context文件夹,用来存放数据库上下文,在Context文件夹下新建类,代码如下
public class PortalContext : DbContext
{
public DbSet<DataDictionary> DataDictionaries { get; set; }
public DbSet<DataDictionaryDetail> DataDictionaryDetails { get; set; }
public DbSet<Setting> Settings { get; set; }
public PortalContext(DbContextOptions<PortalContext> options)
: base(options)
{
}
}
然后我们需要添加一下2张表的映射关系,这两张表之间是一对多的关系,我们在重写OnModelCreating方法中添加如下代码建立两张表的联系
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<DataDictionary>()
.HasMany(data => data.Details)
.WithOne(dataDetail => dataDetail.Dictionary)
.HasForeignKey(dataDetail => dataDetail.ParentId);
}
3.4 把PortalContext注入到DI系统中
在Startup.cs中的ConfigureServices方法中添加如下代码
services.AddDbContext<PortalContext>(builder =>
{
string connString = Configuration.GetConnectionString("DefaultConnection");
builder.UseSqlServer(connString);
});
DefaultConnection配置在appsettings.json文件中
"ConnectionStrings": {
"DefaultConnection": "Data Source=LAPTOP-1UNDDFV3\\SQLEXPRESS;Initial Catalog=Portal_DB;Integrated Security=True"
}
到这里已经完成了基本的编码工作了,下面就是在Controller中获取和修改数据了
4.获取和修改数据
我们在框架默认创建的Values控制器中添加_context字段,并且注入上面创建的上下文
private readonly PortalContext _context;
public ValuesController(PortalContext context)
{
_context = context;
}
4.1 获取数据
在Get方法中,该方法接收一个parentId和userId参数,用来获取该parentId下的所有图标,其中用户要显示在首页的图标使用左外连接来区分(即enable列表),代码如下
[HttpGet]
public JsonResult Get(string parentId, string userId)
{
var details = (from d in _context.DataDictionaryDetails
join s in _context.Settings
on new { detailId = d.Id, userId = new Guid(userId) } equals new { detailId = s.DetailId.Value, userId = s.UserId.Value } into setting
from s in setting.DefaultIfEmpty()
where d.ParentId.ToString() == parentId
orderby s.SortCode
select new
{
d.Id,
d.Code,
d.FullName,
d.ShortName,
d.ImagePath,
d.RedirectUrl,
Setting = s
}).ToList();
return Json(new
{
enable = details.Where(_ => _.Setting != null),
notEnable = details.Where(_ => _.Setting == null)
});
}
4.2 修改数据
在Post方法中,该方法有一个类型的集合,遍历该集合,如果集合中某个Setting的IsDelete为true,则删除该条数据;如果Setting的Id为null,则新增;否则为修改,代码如下
[HttpPost]
public bool Post(IEnumerable<Setting> settings)
{
foreach (Setting setting in settings)
{
if (setting.IsDelete)
{
_context.Settings.Remove(setting);
}
else if (setting.Id == Guid.Empty)
{
setting.Id = Guid.NewGuid();
_context.Settings.Add(setting);
}
else
{
EntityEntry<Setting> entityEntry = _context.Entry(setting);
entityEntry.State = EntityState.Modified;
entityEntry.Property(e => e.DetailId).IsModified = false;
entityEntry.Property(e => e.UserId).IsModified = false;
}
}
return _context.SaveChanges() > 0;
}
5.测试接口
运行项目,在浏览器中输入http://localhost:5000/api/values?parentId=ACB951B9-EA43-4F71-9E45-081229E3F26A&userId=FBAD9A6E-89D1-49E9-9CBD-F1D04C67443A,就可以看到Get方法返回的数据
在PostMan中,调用Post方法来修改一条数据和新增一条数据,把id为E2B44D59-94C1-4AC1-9707-511F3C79A0B7的这条数据的SortCode修改为3;新增一条DetailId为5B9E490D-DEC4-40D8-88BC-340EE919F2F3,SortCode为0的数据,可以看到接口返回true
再次调用Get方法,可以看到enables数组里Id为E2B44D59-94C1-4AC1-9707-511F3C79A0B7的数据的SortCode正确修改为3,并且也成功添加了一条数据