Blazor实战——Known框架增删改查导

这篇具有很好参考价值的文章主要介绍了Blazor实战——Known框架增删改查导。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本章介绍学习增、删、改、查、导功能如何实现,下面以商品资料作为示例,该业务栏位如下:

类型、编码、名称、规格、单位、库存下限、库存上限、备注文章来源地址https://www.toymoban.com/news/detail-458279.html

1. 前后端共用

1.1. 创建实体类

  • 在KIMS项目Entities文件夹下创建KmGoods实体类
  • 该类继承EntityBase类
  • 属性使用Column特性描述,用于生成页面字段和数据校验
public class KmGoods : EntityBase
{
    [Column("商品类型", "", true, "1", "50")]
    public string? Type { get; set; }
	......
    [Column("库存下限", "", false)]
    public decimal? MinStock { get; set; }
	......
    [Column("备注", "", false)]
    public string? Note { get; set; }
}

1.2. 创建Client类

  • 在KIMS项目Clients文件夹下创建GoodsClient类
  • 该类是前后端数据交互接口,继承ClientBase类
  • 该类只需提供分页查询、删除和保存,导入功能由框架统一异步处理
public class GoodsClient : ClientBase
{
    public GoodsClient(Context context) : base(context) { }

    public Task<PagingResult<KmGoods>> QueryGoodsesAsync(PagingCriteria criteria) => Context.QueryAsync<KmGoods>("Goods/QueryGoodses", criteria);
    public Task<Result> DeleteGoodsesAsync(List<KmGoods> models) => Context.PostAsync("Goods/DeleteGoodses", models);
    public Task<Result> SaveGoodsAsync(object model) => Context.PostAsync("Goods/SaveGoods", model);
}

2. 前端

2.1. 创建List页面

  • 在KIMS.Razor项目BaseData文件夹下创建GoodsList类
  • 该类是数据列表页面,继承WebGridView<KmGoods, GoodsForm>类
  • 列表页面按钮和栏位在框架模块管理中配置
class GoodsList : WebGridView<KmGoods, GoodsForm>
{
    //分页查询
    protected override Task<PagingResult<KmGoods>> OnQueryData(PagingCriteria criteria)
    {
        return Client.Goods.QueryGoodsesAsync(criteria);
    }
    //表格栏位格式化显示
    protected override void FormatColumns()
    {
        Column(c => c.Type).Select(new SelectOption { Codes = AppDictionary.GoodsType });
        Column(c => c.TaxRate).Template((b, r) => b.Text(r.TaxRate?.ToString("P")));
    }

    public void New() => ShowForm();//新增按钮方法
    public void DeleteM() => DeleteRows(Client.Goods.DeleteGoodsesAsync);//批量删除按钮方法
    public void Edit(KmGoods row) => ShowForm(row);//编辑操作方法
    public void Delete(KmGoods row) => DeleteRow(row, Client.Goods.DeleteGoodsesAsync);//删除操作方法
}

2.2. 创建Form页面

  • 在KIMS.Razor项目BaseData\Forms文件夹下创建GoodsForm类
  • 该类是数据编辑和查看明细页面,继承WebForm
[Dialog(800, 420)]//设置对话框大小
class GoodsForm : WebForm<KmGoods>
{
    //表单布局
    protected override void BuildFields(FieldBuilder<KmGoods> builder)
    {
        builder.Hidden(f => f.Id);//隐藏字段
        builder.Table(table =>
        {
            table.ColGroup(15, 35, 15, 35);
            table.Tr(attr =>
            {
                table.Field<Text>(f => f.Code).Enabled(TModel.IsNew).Build();//编码,编辑时灰显
                table.Field<Text>(f => f.Name).Build();
            });
            table.Tr(attr =>
            {
                table.Field<Select>(f => f.Type).Set(f => f.Codes, AppDictionary.GoodsType).Build();//下拉框
                table.Field<Select>(f => f.Unit).Set(f => f.Codes, AppDictionary.GoodsUnit).Build();
            });
            table.Tr(attr => table.Field<Text>(f => f.Model).ColSpan(3).Build());
            table.Tr(attr => table.Field<RadioList>(f => f.TaxRate).ColSpan(3).Set(f => f.Items, AppDictionary.TaxRates).Build());//单选按钮
            table.Tr(attr =>
            {
                table.Field<Number>(f => f.MinStock).Build();//数值框
                table.Field<Number>(f => f.MaxStock).Build();
            });
            table.Tr(attr => table.Field<TextArea>(f => f.Note).ColSpan(3).Build());//文本域
        });
    }
    //表单底部按钮
    protected override void BuildButtons(RenderTreeBuilder builder)
    {
        builder.Button(FormButton.Save, Callback(OnSave), !ReadOnly);
        base.BuildButtons(builder);
    }
    //保存按钮方法
    private void OnSave() => SubmitAsync(Client.Goods.SaveGoodsAsync);
}

3. 后端

3.1. 创建Controller类

  • 在KIMS.Core项目Controllers文件夹下创建GoodsController类
  • 该类为服务端WebApi,继承BaseController类
[Route("[controller]")]
public class GoodsController : BaseController
{
    private GoodsService Service => new(Context);

    [HttpPost("[action]")]
    public PagingResult<KmGoods> QueryGoodses([FromBody] PagingCriteria criteria) => Service.QueryGoodses(criteria);

    [HttpPost("[action]")]
    public Result DeleteGoodses([FromBody] List<KmGoods> models) => Service.DeleteGoodses(models);

    [HttpPost("[action]")]
    public Result SaveGoods([FromBody] object model) => Service.SaveGoods(GetDynamicModel(model));//转成dynamic类型
}

3.2. 创建Service类

  • 在KIMS.Core项目Services文件夹下创建GoodsService类
  • 该类为业务逻辑服务类,继承ServiceBase类
class GoodsService : ServiceBase
{
    internal GoodsService(Context context) : base(context) { }
    //分页查询
    internal PagingResult<KmGoods> QueryGoodses(PagingCriteria criteria)
    {
        return GoodsRepository.QueryGoodses(Database, criteria);
    }
    //删除数据
    internal Result DeleteGoodses(List<KmGoods> models)
    {
        if (models == null || models.Count == 0)
            return Result.Error(Language.SelectOneAtLeast);

        //此处增加删除数据校验
        return Database.Transaction(Language.Delete, db =>
        {
            foreach (var item in models)
            {
                db.Delete(item);
            }
        });
    }
    //保存数据
    internal Result SaveGoods(dynamic model)
    {
        var entity = Database.QueryById<KmGoods>((string)model.Id);
        entity ??= new KmGoods { CompNo = CurrentUser.CompNo };
        entity.FillModel(model);
        var vr = entity.Validate();
        if (vr.IsValid)
        {
            if (GoodsRepository.ExistsGoods(Database, entity))
                return Result.Error("商品编码已存在。");
        }

        if (!vr.IsValid)
            return vr;

        return Database.Transaction(Language.Save, db =>
        {
            if (entity.IsNew)
            {
                entity.Code = GetGoodsMaxNo(db);
            }
            db.Save(entity);
        }, entity.Id);
    }
    //获取商品最大编码
    private static string GetGoodsMaxNo(Database db)
    {
        var prefix = "G";
        var maxNo = GoodsRepository.GetGoodsMaxNo(db, prefix);
        if (string.IsNullOrWhiteSpace(maxNo))
            maxNo = $"{prefix}0000";
        return GetMaxFormNo(prefix, maxNo);
    }
}

3.3. 创建Repository类

  • 在KIMS.Core项目Repositories文件夹下创建GoodsRepository类
  • 该类为数据访问类
class GoodsRepository
{
    //分页查询
    internal static PagingResult<KmGoods> QueryGoodses(Database db, PagingCriteria criteria)
    {
        var sql = "select * from KmGoods where CompNo=@CompNo";
        return db.QueryPage<KmGoods>(sql, criteria);//查询条件自动绑定
    }
    //获取商品最大编码
    internal static string GetGoodsMaxNo(Database db, string prefix)
    {
        var sql = $"select max(Code) from KmGoods where CompNo=@CompNo and Code like '{prefix}%'";
        return db.Scalar<string>(sql, new { db.User.CompNo });
    }
    //判断商品是否已存在
    internal static bool ExistsGoods(Database db, KmGoods entity)
    {
        var sql = "select count(*) from KmGoods where Id<>@Id and Code=@Code";
        return db.Scalar<int>(sql, new { entity.Id, entity.Code }) > 0;
    }
}

3.4. 创建Import类

  • 在KIMS.Core项目Imports文件夹下创建KmGoodsImport类(约定:类名以实体类名+Import)
  • 该类为数据异步导入处理类,由框架自动调用,继承BaseImport类
class KmGoodsImport : BaseImport
{
    public KmGoodsImport(Database database) : base(database) { }
    //定义导入栏位,自动生成导入规范
    public override List<ImportColumn> Columns
    {
        get
        {
            return new List<ImportColumn>
            {
                new ImportColumn("商品类型", true),
                new ImportColumn("商品编码", true),
                new ImportColumn("商品名称", true),
                new ImportColumn("计量单位", true),
                new ImportColumn("规格型号", true),
                new ImportColumn("税率"),
                new ImportColumn("库存下限"),
                new ImportColumn("库存上限"),
                new ImportColumn("备注")
            };
        }
    }
    //异步导入处理逻辑
    public override Result Execute(SysFile file)
    {
        var models = new List<KmGoods>();
        var result = ImportHelper.ReadFile(file, row =>
        {
            var model = new KmGoods
            {
                CompNo = file.CompNo,
                Type = row.GetValue("商品类型"),
                Code = row.GetValue("商品编码"),
                Name = row.GetValue("商品名称"),
                Unit = row.GetValue("计量单位"),
                Model = row.GetValue("规格型号"),
                TaxRate = row.GetValue<decimal?>("税率"),
                MinStock = row.GetValue<decimal?>("库存下限"),
                MaxStock = row.GetValue<decimal?>("库存上限"),
                Note = row.GetValue("备注")
            };
            var vr = model.Validate();
            if (vr.IsValid)
            {
                if (models.Exists(m => m.Code == model.Code))
                    vr.AddError("商品编码不能重复!");
                else if (GoodsRepository.ExistsGoods(Database, model))
                    vr.AddError($"系统已经存在该商品编码!");
            }

            if (!vr.IsValid)
                row.ErrorMessage = vr.Message;
            else
                models.Add(model);
        });

        if (!result.IsValid)
            return result;

        return Database.Transaction("导入", db =>
        {
            foreach (var item in models)
            {
                db.Save(item);
            }
        });
    }
}

4. 运行测试

  • 运行效果如下

5. 相关资料

  • 基于C#和Blazor开发的前后端分离框架
  • Blazor实战——Known框架快速开始
  • Blazor实战——Known框架功能配置

到了这里,关于Blazor实战——Known框架增删改查导的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【入门篇】本章包括创建云项目、数据库的使用、云存储管理、云函数的基本使用、实战举例(小程序之云函数开发入门到使用发布上线实操)

    云函数 云函数相当于服务器接口的概念,它并属于小程序端代码。它是以函数的形式运行后端代码来响应事件以及调用其他服务。运行环境是Node.js。 一、基创建云函数项目 打开微信开发者工具: 打开微信开发者工具,并登录你的微信开发者账号。 创建项目: 如果还没有创

    2024年04月26日
    浏览(45)
  • 【项目实战】分布式计算和通信框架(AKKA)入门介绍

    Akka是一个用于构建高并发、分布式、可容错、事件驱动的应用程序的工具包和运行时。它基于Actor模型,提供了一种高效的并发编程模型,可以轻松地编写出高并发、分布式、可容错的应用程序。Akka还提供了一些常用的组件,如路由、集群、持久化等,可以帮助开发人员更加

    2024年02月08日
    浏览(56)
  • 实战演练|从原理到应用:DeepKE框架介绍及简单使用

    本文主要参考deepKE官方文档,以及deepKE官方框架源码https://github.com/zjunlp/DeepKE,我此时使用的DeepKE最新版本是2.1.1。 DeepKE是一个开源的知识图谱抽取与构建工具,支持 cnSchema、低资源、长篇章、多模态 的知识抽取工具,可以基于 PyTorch 实现 命名实体识别 、 关系抽取 和 属性

    2024年02月15日
    浏览(43)
  • 基于 XAF Blazor 的规则引擎编辑器 - 实战篇

    示例项目:https://gitee.com/easyxaf/recharge-rules-engine-sample 继上一篇文章对规则引擎编辑器进行了初步介绍之后,本文将通过实际应用案例深入探讨规则引擎编辑器的使用方法。编辑器的操作相对简单,我们将重点放在RulesEngine的讲解上。请注意,本文不是RulesEngine的入门教程,如

    2024年03月15日
    浏览(46)
  • 如何使用 Blazor 框架在前端浏览器中导入和导出 Excel

    摘要:本文由葡萄城技术团队于博客园原创并首发。转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。 Blazor 是一个相对较新的框架,用于构建具有 .NET 强大功能的交互式客户端 Web UI。一个常见的用例是将现有的 Excel 文件导

    2024年02月06日
    浏览(45)
  • 【ROS2机器人入门到实战】Nav2导航框架介绍与安装

    当前平台文章汇总地址:ROS2机器人从入门到实战 获取完整教程及配套资料代码,请关注公众号鱼香ROS获取 教程配套机器人开发平台:两驱版| 四驱版 为方便交流,搭建了机器人技术问答社区:地址 fishros.org.cn 上一节我们对机器人导航过程中所用到的2D地图进行了介绍,本节

    2024年02月04日
    浏览(41)
  • 从零开始的Django框架入门到实战教程(内含实战实例) - 01 创建项目与app、加入静态文件、模板语法介绍(学习笔记)

      Django是目前比较火爆的框架,之前有在知乎刷到,很多毕业生进入大厂实习后因为不会git和Django框架3天就被踢掉了,因为他们很难把自己的工作融入到整个组的工作中。因此,我尝试自学Django并整理出如下笔记。   在这部分,我将从Django的安装讲起,从创建项目到制

    2024年02月09日
    浏览(72)
  • 回声消除(AEC)原理、算法及实战——完整的回声消除算法框架所涉及到的模块介绍

    一、一个完整的回声消除系统,包含以下几个模块: 1.时延估计(Time Delay Estimation, TDE) 模块 2.(线性)回声消除(Linear Acoustic Echo Cancellation, AEC) 模块(线性滤波模块) 3.双讲检测(Double-Talk Detect, DTD) 模块 4.非线性残余声学回声抑制(Residual Acoustic Echo Suppression, RAES) 模块(

    2024年02月04日
    浏览(38)
  • Django框架 靓号管理(增删改查)

    新建一个项目 backend 使用pycharm创建app 项目目录 app/models.py 数据库配置并注册app backend/settings.py 迁移数据模型 查看数据库表 在数据库模拟创建数据 url 函数 获取所有靓号 通过html+render将靓号罗列出 backend/urls.py app/views.py 在app下创建templates目录 app/templates/pretty_list.html 启动服务

    2024年02月12日
    浏览(32)
  • gin+gorm增删改查目录框架

    从网上找资料,发现,很多都是直接的结构 路由,后端的controller层,还有model层,都是放在了同一个main.go文件中,如果写项目的话,还得自己去拆文件,拆代码,经过查询和自己总结,下面放一个目录框架 总体目录结构 按照业务流程顺序,解释说明 1、加载自定义封装函数文

    2024年01月19日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包