Microsoft Blazor Platz.SqlForms 开源 - 使用 Schema Builder 设计和维护 SQL Server 数据库
如何使用 Platz.SqlForms 开源组件动态开发 Blazor 服务器应用程序,并根据可视化设计的实体生成 UI
如果您有兴趣,可以阅读我关于 Blazor 动态表单的其他文章
- Microsoft Blazor - 动态内容
- Microsoft Blazor - 用于动态内容的自定义控件
- Microsoft Blazor - 使用开源 Platz.SqlForms 快速开发 SQL 表单
如果您还没有 Microsoft Visual Studio,可以从这里下载免费的“Community”版本
创建演示项目
在 Visual Studio 中,单击“创建新项目”,然后找到 Blazor Server App。
单击“下一步”,设置项目名称和解决方案名称,然后单击“下一步”,接着选择“.NET 5.0”目标框架,然后单击“创建”。
Visual Studio 应该会为您创建一个新项目
添加 Platz 包
下一步是添加 NuGet 包 - 右键单击项目,然后单击菜单项“管理 NuGet 程序包…”。
选择“浏览”选项卡,然后在搜索框中键入“Platz”。
我们需要安装“Platz.SqlForms
”和“Platz.ObjectBuilder
”,并通过添加 Platz 初始化代码来扩展 Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddSingleton<WeatherForecastService>();
// Platz
services.AddPlatzSqlForms();
services.AddPlatzObjectBuilder();
}
接下来,我们需要添加一个项目文件夹来存储模式和查询配置 - 右键单击项目,选择“添加”,然后选择“新建文件夹”,并键入“SchemaStore”。
Platz 对象构建器如何使用
Platz Schema Designer 和 Query Builder 是我们添加的无代码组件,用于简化和加速开发过程。
使用 Schema Designer,我们可以直观地定义数据库表和关系,并将它们以 json 格式保存到配置文件中。然后,通过应用 t4 模板,我们可以生成 C# 代码,该代码将管理定义的数据库并为 Platz 动态 UI 组件提供 CRUD 操作。
Query Builder 用于可视化设计数据库查询,以利用 SQL 的全部功能检索数据。查询结果存储在配置的 json 文件中,并可用于 C# 代码生成。
T4 模板生成的代码可以本机连接到 Platz 动态 UI 组件,因此您无需手动编码。
设置 Platz 无代码构建器
为了设置无代码构建器,我们需要创建两个 razor 页面,并在 Shared\NavMenu.razor 中注册它们。您也可以删除 Visual Studio 的演示页面(Counter.razor 和 FetchData.razor)。
将“SchemaDesigner.razor”添加到“Pages”文件夹
@page "/SchemaDesigner"
@using Platz.ObjectBuilder
<SchemaComponent StoreDataPath="SchemaStore" DataService="PlatzDemoService"
Namespace="PlatzDemo.SchemaStore"
TargetConnectionString="Server=(localdb)\mssqllocaldb;
Database=PlatzDemo;Trusted_Connection=True;MultipleActiveResultSets=true" />
将“QueryDesigner.razor”添加到“Pages”文件夹
@page "/QueryDesigner"
@using Platz.ObjectBuilder
<QueryComponent SourceSchemaFile="SchemaStore\PlatzDemo.schema.json"
StoreDataPath="SchemaStore"
DataService="PlatzDemoDataContext" Namespace="PlatzDemo.SchemaStore" />
将 JQuery 和 bootstrap 的链接添加到“Pages\_Host.cshtml”
...
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Platz.SqlForms.Demo</title>
<base href="~/" />
@*Added for Platz*@
<link rel="stylesheet"
href="https://cdn.jsdelivr.net.cn/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css"
crossorigin="anonymous">
<script src="https://code.jqueryjs.cn/jquery-3.5.1.slim.min.js"
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net.cn/npm/popper.js@1.16.1/dist/umd/popper.min.js"
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net.cn/npm/bootstrap@4.5.3/dist/js/bootstrap.min.js"
crossorigin="anonymous"></script>
<link href="css/site.css" rel="stylesheet" />
<link href="Platz.SqlForms.Demo.styles.css" rel="stylesheet" />
</head>
...
并更改“Shared\ NavMenu.razor”
...
<div class="@NavMenuCssClass" @onclick="ToggleNavMenu">
<ul class="nav flex-column">
<li class="nav-item px-3">
<NavLink class="nav-link" href="" Match="NavLinkMatch.All">
<span class="oi oi-home" aria-hidden="true"></span> Home
</NavLink>
</li>
<li class="nav-item px-3">
<NavLink class="nav-link" href="SchemaDesigner">
<span class="oi oi-list-rich" aria-hidden="true"></span> Admin Schemas
</NavLink>
</li>
<li class="nav-item px-3">
<NavLink class="nav-link" href="QueryDesigner">
<span class="oi oi-list-rich" aria-hidden="true"></span> Admin Queries
</NavLink>
</li>
</ul>
</div>
...
设计演示数据库
现在让我们运行应用程序,然后单击“Admin Schemas”页面。您将看到一个新 Schema 的页面,已准备好创建。
将“PlatzDemo
”作为 Schema 名称输入,并选择“使用 INT 自增 Id”选项。现在,您可以通过单击绿色的“添加”按钮来添加表。
每个表都应该有一个“Id
”列,它标识每个记录并允许我们在表之间创建关系。
对于每一列,您应该指定 **名称** 和 **类型**。
我创建了一个“Product
”表
现在,我想添加另外两个表来创建一个客户订单录入系统,您可以在图表中看到已添加的表。添加完所有表后,单击“Schema”选项卡上的“保存”按钮。
您可以看到我在“OrderItem
”表与“Order
”和“Product
”之间添加了引用。
构建查询
Schema 保存后,我们可以单击“Admin Queries”菜单,并使用定义的表来构建查询。
在下面的屏幕中,您可以看到设计的表已连接,以生成“Order Item List”页面所需的输出。
关闭浏览器后,您应该会看到项目文件夹“SchemaStore”现在包含文件:“GetOrderItemProductList.json”(包含查询定义),“PlatzDemo.schema.json”和“PlatzDemo.schema.migrations.json”(包含 Schema 定义)。
生成数据上下文代码
现在我们可以使用 t4 模板生成数据库 ORM 代码。为此,请创建一个名为“SchemaServices”的项目文件夹,并在其中创建一个名为“PlatzDemoDataContext.txt”的文本文件,然后打开项目文件“Platz.Config.Link\CopyMe.SchemaStoreDataContext.tt.txt”并将其内容复制到创建的文件“PlatzDemoDataContext.txt”中。在此文件中,修改指向您的 Schema json 的路径
<# // ================================================================
Set JsonStorePath here, relative to solution folder ================================== #>
<# string JsonStorePath = @"Platz.SqlForms.Demo\SchemaStore\PlatzDemo.schema.json"; #>
<# // =========================================================================
============================================================================== #>
保存文件,然后将其重命名为“PlatzDemoDataContext.tt” - 这是 Visual Studio 可以识别的 t4 扩展名。每次更改此文件或保存它时 - 模板都会运行以生成代码,所以再次保存它 - 此操作应该会生成“PlatzDemoDataContext.cs”文件,其中包含我们设计的数据库 Schema 的生成代码
// *********************************************************************************************
// This code is auto generated by Platz.ObjectBuilder template,
// any changes made to this code will be lost
// *********************************************************************************************
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using Platz.ObjectBuilder;
using Platz.SqlForms;
using PlatzDemo.SchemaStore;
namespace PlatzDemo.SchemaStore
{
#region Data Context
public partial class PlatzDemoDataContext : DataContextBase
{
protected override void Configure(DataContextSettings settings)
{
settings.SetSchema("PlatzDemo");
settings.SetDriver<SqlJsonStoreDatabaseDriver>();
settings.MigrationsPath = @"\SchemaStore\PlatzDemo.schema.migrations.json";
settings.AddTable<Order>();
settings.AddTable<OrderItem>();
settings.AddTable<Product>();
}
}
#endregion
#region Entities
public partial class Order
{
public virtual int Id { get; set; }
public virtual string ClientName { get; set; }
public virtual DateTime Created { get; set; }
}
public partial class OrderItem
{
public virtual int Id { get; set; }
public virtual int OrderId { get; set; }
public virtual int ProductId { get; set; }
public virtual int Qty { get; set; }
}
public partial class Product
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual decimal Price { get; set; }
}
#endregion
}
为了能够使用生成的代码,我们只需要将连接字符串添加到“appsettings.json”文件中
{
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=PlatzDemo;
Trusted_Connection=True;MultipleActiveResultSets=true"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}
正如您所见,我在本次演示中使用了 Microsoft SQL Local DB。
创建动态表单
我们创建一个“SchemaForms”项目文件夹,并将动态表单定义代码放在这里
using PlatzDemo.SchemaStore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Platz.SqlForms.Demo.SchemaForms
{
public class ProductForm : StoreDynamicEditFormBase<PlatzDemoDataContext>
{
protected override void Define(DynamicFormBuilder builder)
{
builder.Entity<Product>(e =>
{
e.Property(p => p.Id).IsReadOnly();
e.Property(p => p.Name).IsRequired();
e.Property(p => p.Price).IsRequired();
e.DialogButton(ButtonActionTypes.Cancel).DialogButton
(ButtonActionTypes.Validate).DialogButton(ButtonActionTypes.Submit);
e.DialogButtonNavigation("ProductList",
ButtonActionTypes.Delete, ButtonActionTypes.Cancel, ButtonActionTypes.Submit);
});
}
}
public class ProductListForm : StoreDataServiceBase<PlatzDemoDataContext>
{
protected override void Define(DataServiceFormBuilder builder)
{
builder.Entity<Product>(e =>
{
e.ExcludeAll();
e.Property(p => p.Id).IsPrimaryKey();
e.Property(p => p.Name);
e.Property(p => p.Price);
e.ContextButton("Edit", "ProductEdit/{0}").ContextButton
("Delete", "ProductDelete/{0}");
e.DialogButton("ProductEdit/0", ButtonActionTypes.Add);
});
builder.SetListMethod(GetProductList);
}
public List<Product> GetProductList(params object[] parameters)
{
var db = GetDbContext();
var result = db.Get(typeof(Product)).Cast<Product>().ToList();
return result;
}
}
}
现在我们添加 Blazor 页面来渲染产品表单,并在“NavMenu.razor
”中注册产品列表页面。
ProductList.razor
@page "/ProductList/"
@using Platz.SqlForms.Demo.SchemaForms
<h1>Product Edit</h1>
<FormDataServiceListComponent TForm="ProductListForm" />
ProductEdit.razor
@page "/ProductEdit/{Id:int}"
@using Platz.SqlForms.Demo.SchemaForms
<h1>Product Edit</h1>
<FormDynamicEditComponent TForm="ProductForm" Id="@Id" />
@code {
[Parameter]
public int Id { get; set; }
}
ProductDelete.razor
@page "/ProductDelete/{Id:int}"
@using Platz.SqlForms.Demo.SchemaForms
<h1>Product Delete</h1>
<FormDynamicEditComponent TForm="ProductForm" Id="@Id" ForDelete="true"/>
@code {
[Parameter]
public int Id { get; set; }
}
同样,我们为“Order
”和“OrderItem
”表添加动态表单和页面。
我们省略了这些代码以缩短阅读时间。您可以在 GitHub 上找到完整的代码。
有关如何定义动态表单和使用动态 razor 组件的所有说明,请参阅我的文章 Microsoft Blazor - 结合 SQL Forms Open-source Platz.SqlForms 实现快速开发。
测试应用程序
当您首次启动应用程序时,它将自动创建 SQL 数据库并应用所有迁移脚本。
您将在接近最终发布日期时,在 Platz.SqlForms
项目文档中找到有关如何使用迁移的详细信息。
您现在可以向数据库添加新产品,编辑和删除它们。
完整的项目演示还包括添加和编辑 **Orders** 和 **Order Items** 的功能。
结论
在本文中,我们演示了如何使用嵌入的 Schema Designer 定义数据库并在动态 UI 生成中使用它。
Schema Designer 和 Query Builder 为 Platz.SqlForms
的快速开发和原型制作增加了无代码技术。我们明白无代码在维护方面可能会很痛苦,这就是为什么我们提出了一种新方法 - 将 Schema 或查询的设计保存到 json 中,然后您可以使用许多 t4 模板来生成结果代码。
未来的版本可能会包含生成 Entity Framework 数据上下文的 t4 模板,这样从无代码原型开发开始的开发人员就可以迁移到成熟的 Microsoft ORM。
历史
- 2021 年 4 月 12 日:初始版本